mirror of
https://github.com/appium/appium.git
synced 2026-11-02 07:13:52 +08:00
Compare commits
214
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d16ac6b45 | ||
|
|
6ea0830319 | ||
|
|
228b091edc | ||
|
|
81a5b57673 | ||
|
|
8d94f48bc5 | ||
|
|
f03468a153 | ||
|
|
6a78aa9cea | ||
|
|
9c5407ce64 | ||
|
|
2a99e43b88 | ||
|
|
dca88624a4 | ||
|
|
69f100ad3e | ||
|
|
f5e708ac42 | ||
|
|
c91683f50f | ||
|
|
4a2bfe9418 | ||
|
|
3008c0d7be | ||
|
|
9a3f990739 | ||
|
|
16c3ae25ea | ||
|
|
93fa5ccb06 | ||
|
|
8590432955 | ||
|
|
42ef4841f9 | ||
|
|
8daf5e123a | ||
|
|
3108a162ff | ||
|
|
942057d26c | ||
|
|
6ba31fe576 | ||
|
|
7abf277ea3 | ||
|
|
9aa9807b90 | ||
|
|
abc9ebb9e8 | ||
|
|
522f05d25e | ||
|
|
59a84424f2 | ||
|
|
c82cbfeb58 | ||
|
|
b6aa5ace6e | ||
|
|
6c4fd35332 | ||
|
|
07d5fd1c4f | ||
|
|
f9920e2c1b | ||
|
|
e22a94ea77 | ||
|
|
a25d8f129c | ||
|
|
8df9c63127 | ||
|
|
760961c5eb | ||
|
|
54b4879700 | ||
|
|
9cfdc8652b | ||
|
|
7f99d3bdb9 | ||
|
|
e02608a373 | ||
|
|
f91d8c8812 | ||
|
|
a5389e648a | ||
|
|
d6b40797d3 | ||
|
|
22c71fa462 | ||
|
|
bd92186bfc | ||
|
|
c13ea56c6d | ||
|
|
268b24ff83 | ||
|
|
3696ac1d8d | ||
|
|
b0d8a4c3f4 | ||
|
|
9c9fa612a1 | ||
|
|
9d21f56edb | ||
|
|
c694d7cc6f | ||
|
|
d04665777a | ||
|
|
b39cfd99e3 | ||
|
|
8606bdb650 | ||
|
|
e19bad2bc0 | ||
|
|
237e589b7c | ||
|
|
c8d63532b8 | ||
|
|
0437720e36 | ||
|
|
850b095ac0 | ||
|
|
95406b603e | ||
|
|
275da089e4 | ||
|
|
7e19c88b79 | ||
|
|
b167e765af | ||
|
|
522e0d5b6f | ||
|
|
4953dfa655 | ||
|
|
a9d4b5a30e | ||
|
|
6a379c242f | ||
|
|
e3bce2b6be | ||
|
|
905f84faf5 | ||
|
|
f243787481 | ||
|
|
e5f6cd9617 | ||
|
|
805156bd8b | ||
|
|
fdcf234e51 | ||
|
|
7860c05285 | ||
|
|
d5a9e3926c | ||
|
|
4dc98932db | ||
|
|
f548edc0d5 | ||
|
|
b0095bfd47 | ||
|
|
15b783179d | ||
|
|
66ff497600 | ||
|
|
846dd52886 | ||
|
|
4a896b7dc8 | ||
|
|
e69f7fd1ad | ||
|
|
76cc279ad9 | ||
|
|
bdc0bf4670 | ||
|
|
db4ed63de4 | ||
|
|
46278a1752 | ||
|
|
958fca47c8 | ||
|
|
00cd1b4b0f | ||
|
|
809477c70c | ||
|
|
6bbb81724d | ||
|
|
4dc0a07884 | ||
|
|
438b9da543 | ||
|
|
de17d3762e | ||
|
|
e3f7bd07f7 | ||
|
|
ed6c6dd544 | ||
|
|
b56b180f34 | ||
|
|
12969268fe | ||
|
|
b312028d7e | ||
|
|
8d7cec96d8 | ||
|
|
0e443d2799 | ||
|
|
5c41112134 | ||
|
|
dd52d04b21 | ||
|
|
0e52da4b3a | ||
|
|
98eed2d13f | ||
|
|
371568da36 | ||
|
|
56618886ed | ||
|
|
ab12235483 | ||
|
|
08f05562c1 | ||
|
|
a1d35404a2 | ||
|
|
a16c4c9521 | ||
|
|
a2b0ba8773 | ||
|
|
796ca9f98f | ||
|
|
69e9abeed3 | ||
|
|
cabc114935 | ||
|
|
aa86ef9603 | ||
|
|
656ba166e1 | ||
|
|
e8886ae0d2 | ||
|
|
122a1863de | ||
|
|
0bbd2f8a76 | ||
|
|
f03816cca5 | ||
|
|
e1e478cf32 | ||
|
|
c799629b7d | ||
|
|
1d9821352a | ||
|
|
b8b0e42f69 | ||
|
|
6a8f26a9cb | ||
|
|
e65c1cdaed | ||
|
|
da7a4fdce8 | ||
|
|
f344504f15 | ||
|
|
f0de55da0d | ||
|
|
6704491be0 | ||
|
|
2a68d05b4d | ||
|
|
5553016582 | ||
|
|
9879d9f9b8 | ||
|
|
517828be57 | ||
|
|
e791a9b30c | ||
|
|
c2ccc80438 | ||
|
|
a56f0f820a | ||
|
|
b88ff49f80 | ||
|
|
5bde635d19 | ||
|
|
175b7acc27 | ||
|
|
507f2ba8b5 | ||
|
|
1ae1fe9c44 | ||
|
|
c70faded35 | ||
|
|
e922e9738c | ||
|
|
0899725aab | ||
|
|
62be085f95 | ||
|
|
cb9fb9c6fe | ||
|
|
82c5caf0b5 | ||
|
|
bcbb8ee86e | ||
|
|
980aa69b93 | ||
|
|
1cae549a7b | ||
|
|
ef163eb8df | ||
|
|
8c3b3005be | ||
|
|
056baba3a0 | ||
|
|
0ee7716cf0 | ||
|
|
3d674d0085 | ||
|
|
bbe3b6c6e5 | ||
|
|
42d7ed8afe | ||
|
|
5b8cb76ea3 | ||
|
|
d5959902bc | ||
|
|
1d066073dc | ||
|
|
048ce520d8 | ||
|
|
19fb9d608f | ||
|
|
38afce5ea5 | ||
|
|
63cb664af1 | ||
|
|
51c3063194 | ||
|
|
750872af47 | ||
|
|
32645ba726 | ||
|
|
f5f0aa5068 | ||
|
|
00dc1eddaa | ||
|
|
3bf1eaf5a9 | ||
|
|
75710ab823 | ||
|
|
7fe67a286a | ||
|
|
38cc8a343f | ||
|
|
511ff11220 | ||
|
|
ce36003edb | ||
|
|
0e51b9b8b9 | ||
|
|
da3f9ff881 | ||
|
|
dcb6de22ea | ||
|
|
8f20c973f4 | ||
|
|
89e8d2e4d4 | ||
|
|
b692914a95 | ||
|
|
a83f8eee9b | ||
|
|
f583e99e60 | ||
|
|
21dd13e5e5 | ||
|
|
45681602c0 | ||
|
|
efdb1ce6ce | ||
|
|
b6c97cd11e | ||
|
|
fedabb1fdc | ||
|
|
49ac8126a2 | ||
|
|
894c193150 | ||
|
|
688af4ddb4 | ||
|
|
c8e7fa642f | ||
|
|
449dbe9a5c | ||
|
|
2468aeca60 | ||
|
|
9a66f48001 | ||
|
|
ec04635925 | ||
|
|
035e30b892 | ||
|
|
893fc040e1 | ||
|
|
482a1f7bbf | ||
|
|
d17d022224 | ||
|
|
46085635a9 | ||
|
|
db28605532 | ||
|
|
a5ea99aacd | ||
|
|
880111b0ff | ||
|
|
d6cdd3b05f | ||
|
|
326942d8ac | ||
|
|
622b245ea3 | ||
|
|
5034f1afc6 | ||
|
|
a97f3893e6 |
@@ -23,8 +23,6 @@ targets:
|
||||
path: ./packages/appium
|
||||
- type: npm
|
||||
path: ./packages/base-driver
|
||||
- type: npm
|
||||
path: ./packages/doctor
|
||||
- type: npm
|
||||
path: ./packages/eslint-config-appium
|
||||
- type: npm
|
||||
|
||||
@@ -1,51 +1,97 @@
|
||||
name: 🐞 Bug Report
|
||||
description: File a new bug report
|
||||
title: 'bug: <title>'
|
||||
description: Create a new bug report.
|
||||
title: '🐞 bug: <title>'
|
||||
labels: [Bug, Needs Triage]
|
||||
body:
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: ':stop_sign: _For support questions, please visit [http://discuss.appium.io](http://discuss.appium.io) instead._'
|
||||
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: 'Do I have the most recent component updates?'
|
||||
description: 'Appium 1-related issues are going to be ignored as this version has reached its end of life.'
|
||||
options:
|
||||
- label: 'I use the most recent available driver/plugin and server versions'
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: 'Is the component officially supported by the Appium team?'
|
||||
description: 'Make sure you report an issue for a component which is officially supported/maintained by the Appium team.'
|
||||
options:
|
||||
- label: 'I have verified the component repository is present under the Appium organization in GitHub'
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: 'Is there an existing issue for this?'
|
||||
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'
|
||||
- label: I have searched the existing issues
|
||||
required: true
|
||||
- type: textarea
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: 'Current Behavior'
|
||||
description: 'Describe the problem you are experiencing. **Please do not paste your logs here.** Screenshots are welcome.'
|
||||
label: Appium Version
|
||||
description: What Appium server version are you running?
|
||||
placeholder: Output of `appium --version`
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 'Expected Behavior'
|
||||
description: 'Describe what you expect to happen instead.'
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 'Minimal Reproducible Example'
|
||||
description: |
|
||||
Please provide a the _smallest, complete code snippet_ that Appium's maintainers can run to reproduce the issue ([read more about what this entails](https://stackoverflow.com/help/minimal-reproducible-example)). Failing this, any sort of reproduction steps are better than nothing!
|
||||
|
||||
An easy way to get started is to copy [sample code](https://github.com/appium/appium/tree/master/packages/appium/sample-code) and modify it accordingly.
|
||||
- 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:
|
||||
|
||||
@@ -54,39 +100,12 @@ body:
|
||||
- Provide a link to a new or existing public repository exhibiting the issue
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 'Environment'
|
||||
description: 'Please provide the following information about your environment; feel free to remove any items which are not relevant.'
|
||||
value: |
|
||||
- Operating system:
|
||||
- Appium server version (output of `appium --version`):
|
||||
- Appium driver(s) and their version(s) (`appium driver list`):
|
||||
- Appium plugin(s) and their version(s) (`appium plugin list`):
|
||||
- Node.js version (output of `node --version`):
|
||||
- `npm` version (output of `npm --version`):
|
||||
- Last component(s) version which did _not_ exhibit the problem:
|
||||
- Platform and version under test:
|
||||
- Real device or emulator/simulator:
|
||||
validations:
|
||||
required: false
|
||||
- type: input
|
||||
attributes:
|
||||
label: 'Link to Appium Logs'
|
||||
description: |
|
||||
Create a [Gist](https://gist.github.com)—which contains your _full_ Appium logs—and link it here. Alternatively, you can attach a logfile to this issue (drag it into the "Further Information" field below).
|
||||
|
||||
:warning: _Remember to redact or remove any sensitive information!_
|
||||
placeholder: 'https://gist.github.com/...'
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Further Information
|
||||
description: |
|
||||
Links? References? Anything that will give us more context about the issue you are encountering!
|
||||
description: If needed, please provide additional information about your issue (attachments, links, references, etc.).
|
||||
|
||||
_Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in._
|
||||
validations:
|
||||
required: false
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: ':stop_sign: _For support questions, please visit [http://discuss.appium.io](http://discuss.appium.io) instead._'
|
||||
value: ':stop_sign: _Make sure you are reporting an issue. For general questions, please use [http://discuss.appium.io](http://discuss.appium.io)._'
|
||||
|
||||
@@ -2,4 +2,4 @@ blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: ❓ Question
|
||||
url: https://discuss.appium.io/
|
||||
about: Please use the Appium forum for questions
|
||||
about: Please use the Appium forum for any questions.
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[Feat]:"
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -0,0 +1,33 @@
|
||||
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
|
||||
@@ -16,7 +16,7 @@ _Put an `x` in the boxes that apply_
|
||||
|
||||
_Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code._
|
||||
|
||||
- [ ] I have read the [CONTRIBUTING](https://github.com/appium/appium/blob/master/CONTRIBUTING.md) doc
|
||||
- [ ] 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
|
||||
|
||||
@@ -53,11 +53,6 @@ labels:
|
||||
matcher:
|
||||
files: ['packages/base-plugin/**']
|
||||
|
||||
- label: '@appium/doctor'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/doctor/**']
|
||||
|
||||
- label: '@appium/docutils'
|
||||
sync: true
|
||||
matcher:
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Retrieves non-English translations from Crowdin and creates a PR with new changes
|
||||
|
||||
name: Sync Crowdin Docs Translations
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# TODO: Uncomment the scheduler as soon as we have existing translations
|
||||
# imported to Crowdin
|
||||
# schedule:
|
||||
# - cron: 0 0 * * 0
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use Node.js LTS
|
||||
uses: actions/setup-node@v4
|
||||
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@v7.0.5
|
||||
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'
|
||||
@@ -0,0 +1,31 @@
|
||||
# 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@v4
|
||||
- name: Use Node.js LTS
|
||||
uses: actions/setup-node@v4
|
||||
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 }}
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
useRollingCache: true
|
||||
install-command: npm ci
|
||||
- name: Install dependencies (Python)
|
||||
run: pip install -r packages/docutils/requirements.txt
|
||||
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"
|
||||
|
||||
@@ -10,6 +10,8 @@ jobs:
|
||||
fossa-check:
|
||||
name: Run FOSSA Analysis
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
FOSSA_API_KEY: ${{secrets.FOSSA_API_KEY}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -17,10 +19,13 @@ jobs:
|
||||
- name: Install dependencies
|
||||
uses: bahmutov/npm-install@v1
|
||||
- name: Install fossa-cli
|
||||
run: ./scripts/install-fossa.sh -d
|
||||
run: |
|
||||
curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install-latest.sh | bash
|
||||
- name: Run FOSSA analysis
|
||||
run: |
|
||||
fossa analyze
|
||||
fossa test
|
||||
env:
|
||||
FOSSA_API_KEY: ${{secrets.FOSSA_API_KEY}}
|
||||
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
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
name: Conventional Commits
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
conventional:
|
||||
name: PR Title
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: beemojs/conventional-pr-action@v3
|
||||
with:
|
||||
config-preset: angular
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
useRollingCache: true
|
||||
install-command: npm ci
|
||||
- name: Install dependencies (Python)
|
||||
run: pip install -r packages/docutils/requirements.txt
|
||||
run: PIP_BREAK_SYSTEM_PACKAGES=1 pip install -r packages/docutils/requirements.txt
|
||||
- name: Publish docs
|
||||
run: |
|
||||
cd packages/appium
|
||||
|
||||
+4
-1
@@ -1,6 +1,9 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": ["github>appium/appium//renovate/default"],
|
||||
"schedule": ["after 10pm and before 5:00am"],
|
||||
"schedule": [
|
||||
"after 10pm",
|
||||
"before 5:00am"
|
||||
],
|
||||
"timezone": "America/Vancouver"
|
||||
}
|
||||
|
||||
+18
-10
@@ -1,36 +1,44 @@
|
||||
# Aggregate Changelog
|
||||
|
||||
Appium contains many different modules and supports a variety of drivers, plugins and clients, most of which have their own changelogs. Links to these individual changelogs are aggregated here.
|
||||
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 2 Changelog](packages/appium/CHANGELOG.md)
|
||||
* [Appium 1.x Changelog](https://github.com/appium/appium/blob/1.x/CHANGELOG.md)
|
||||
|
||||
## Appium Drivers / Clients / Plugins
|
||||
* Refer to the [Appium Ecosystem](https://appium.io/docs/en/latest/ecosystem/) page for links to specific driver/client/plugin documentation
|
||||
* Changelogs for plugins maintained by Appium Team are also linked in the Other Modules section below
|
||||
## Drivers / Clients
|
||||
Refer to the [Appium Ecosystem](https://appium.io/docs/en/latest/ecosystem/) page for links
|
||||
to driver/client documentation
|
||||
|
||||
## Other Appium Modules
|
||||
## 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)
|
||||
* [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)
|
||||
* [doctor](packages/doctor/CHANGELOG.md)
|
||||
* [docutils](packages/docutils/CHANGELOG.md)
|
||||
* [driver-test-support](packages/driver-test-support/CHANGELOG.md)
|
||||
* [eslint-config-appium](packages/eslint-config-appium/CHANGELOG.md)
|
||||
* [eslint-config-appium-ts](packages/eslint-config-appium-ts/CHANGELOG.md)
|
||||
* [execute-driver-plugin](packages/execute-driver-plugin/CHANGELOG.md)
|
||||
* [fake-driver](packages/fake-driver/CHANGELOG.md)
|
||||
* [fake-plugin](packages/fake-plugin/CHANGELOG.md)
|
||||
* [images-plugin](packages/images-plugin/CHANGELOG.md)
|
||||
* [logger](packages/logger/CHANGELOG.md)
|
||||
* [opencv](packages/opencv/CHANGELOG.md)
|
||||
* [plugin-test-support](packages/plugin-test-support/CHANGELOG.md)
|
||||
* [relaxed-caps-plugin](packages/relaxed-caps-plugin/CHANGELOG.md)
|
||||
* [schema](packages/schema/CHANGELOG.md)
|
||||
* [strongbox](packages/strongbox/CHANGELOG.md)
|
||||
* [support](packages/support/CHANGELOG.md)
|
||||
* [test-support](packages/test-support/CHANGELOG.md)
|
||||
* [tsconfig](packages/tsconfig/CHANGELOG.md)
|
||||
* [types](packages/types/CHANGELOG.md)
|
||||
* [universal-xml-plugin](packages/universal-xml-plugin/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))
|
||||
* [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))
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
# Contributing to Appium
|
||||
|
||||
There are a lot of different ways to contribute to Appium. See below for
|
||||
everything you can do and the processes to follow for each contribution method.
|
||||
Note that no matter how you contribute, your participation is governed by our
|
||||
[Code of Conduct](CONDUCT.md).
|
||||
|
||||
### Make changes to the Appium code or docs
|
||||
|
||||
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. And note
|
||||
that all participation in the Appium community (including code submissions) is
|
||||
governed by our [Code of Conduct](CONDUCT.md). Then, have a look at our
|
||||
[running from source doc](/docs/en/contributing-to-appium/appium-from-source.md) for more
|
||||
information on how to get set up to run tests and start slinging code.
|
||||
|
||||
You will probably also want to have a look at this more in-depth [Developer's
|
||||
Overview](/docs/en/contributing-to-appium/developers-overview.md) of the Appium
|
||||
project, how Appium is architected, how to make changes to modules, and so on.
|
||||
|
||||
Finally, before we accept your code, you will need to have signed our
|
||||
[Contributor License
|
||||
Agreement](https://cla.js.foundation/appium/appium).
|
||||
|
||||
### Become an Appium Triager
|
||||
|
||||
You can help us manage our issue tracker! All you need is enough familiarity
|
||||
with Appium to try and reproduce bugs. We triage issues by having conversations
|
||||
with the issue creator and then either closing the issue or moving it into the
|
||||
[Bugs](https://github.com/appium/appium/milestones/Bugs) or
|
||||
[Features](https://github.com/appium/appium/milestones/Features) milestone. We
|
||||
use these buckets as the backlogs for our upcoming releases.
|
||||
|
||||
We use this "algorithm" for triaging issues, which anyone can jump in and follow:
|
||||
|
||||
1. If issue is a feature request, discuss amongst Appium devs.
|
||||
* If we decide to build it, add to the Features milestone.
|
||||
* If we decide not to build it, just close.
|
||||
2. If issue is a bug report, attempt to verify
|
||||
* If it's a duplicate, close with link to bug already reported.
|
||||
* If it ultimately can't be verified, close until we have enough information to verify (e.g., in most cases we need a full set of Appium logs to help diagnose an issue).
|
||||
* If the user hasn't provided enough information, keep asking for enough information to verify.
|
||||
* If it's a verified new bug, add it to the Bugs milestone.
|
||||
* If we have been waiting for a reply from the user for over 3 weeks, close.
|
||||
|
||||
If you're interested in joining our triage rotation, contact
|
||||
[@jlipps](https://github.com/jlipps) or
|
||||
[@imurchie](https://github.com/imurchie).
|
||||
|
||||
### Help out on our forums
|
||||
|
||||
We can always use help on our forums at
|
||||
[discuss.appium.io](https://discuss.appium.io)! Hop on over and see if there
|
||||
are any questions that you can answer.
|
||||
|
||||
### Submit bug reports or feature requests
|
||||
|
||||
Just use the GitHub issue tracker to submit your bug reports and feature
|
||||
requests. If you are submitting a bug report, please follow the [issue template](https://github.com/appium/appium/issues/new).
|
||||
+3
-4
@@ -67,10 +67,9 @@ significant contributions to the project but are no longer actively committing.
|
||||
|
||||
### Other Contributors
|
||||
|
||||
Other, less formal, kinds of contribution are outlined in our
|
||||
[CONTRIBUTING](/CONTRIBUTING.md) doc. 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:
|
||||
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)
|
||||
|
||||
@@ -9,11 +9,15 @@
|
||||
Cross-platform test automation for native, hybrid, mobile web and desktop apps.
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](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/)
|
||||
|
||||
</div>
|
||||
|
||||
***
|
||||
|
||||
<p align="center"><b>
|
||||
@@ -21,7 +25,7 @@
|
||||
<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://github.com/appium/appium/blob/master/ROADMAP.md">Roadmap</a> |
|
||||
<a href="https://appium.io/docs/en/latest/contributing/">Contributing Guide</a> |
|
||||
<a href="https://discuss.appium.io">Discussion Forum</a>
|
||||
</b></p>
|
||||
|
||||
@@ -190,11 +194,6 @@ rely on. [Become a sponsor](https://opencollective.com/appium) via our OpenColle
|
||||
Appium is incredibly grateful to our Development and Strategic Partners for their sustained
|
||||
contribution of project development and leadership!
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.headspin.io/solutions/appium-mobile-test-automation"><img src="packages/appium/docs/overrides/assets/images/sponsor-logo-headspin.png"
|
||||
width="275" alt="HeadSpin" /></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.browserstack.com/browserstack-appium?utm_campaigncode=701OW00000AoUTQYA3&utm_medium=partnered&utm_source=appium">
|
||||
<picture>
|
||||
@@ -212,7 +211,7 @@ width="300" alt="Sauce Labs" /></a>
|
||||
|
||||
### Other Sponsors
|
||||
|
||||
A full list of sponsors is available at our [Sponsors page](SPONSORS.md).
|
||||
A full list of sponsors is available at our [Sponsors page](https://appium.io/docs/en/latest/sponsors/).
|
||||
|
||||
## License
|
||||
|
||||
|
||||
+1
-46
@@ -1,48 +1,3 @@
|
||||
# Sponsors & Backers
|
||||
|
||||
Appium is an Apache-2 licensed open source project whose development is made possible entirely by
|
||||
donations of time and money by individuals and companies who benefit from our software and our
|
||||
mission. If you'd like to join this amazing group and help ensure Appium's continued development
|
||||
and maintenance, you can contribute via [Appium's OpenCollective
|
||||
Hub](https://opencollective.com/appium).
|
||||
|
||||
## Development Partners
|
||||
|
||||
We are very grateful for the support of our Development Partners, who donate Appium development and
|
||||
maintenance as part of their employees' core job duties!
|
||||
|
||||
<a href="https://www.headspin.io/solutions/appium-mobile-test-automation" target="_blank"><img
|
||||
src="packages/appium/docs/overrides/assets/images/sponsor-logo-headspin.png" width="250"/></a>
|
||||
|
||||
## Strategic Partners
|
||||
|
||||
We are very grateful for the financial and marketing support of our exclusive Strategic Partners,
|
||||
who contribute a significant ongoing investment of funds to help the project attract and reward
|
||||
contributors!
|
||||
|
||||
<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="250" alt="Browserstack"/>
|
||||
</picture>
|
||||
</a>
|
||||
<a style="padding-left: 1em" href="https://saucelabs.com/resources/blog/appium-strategic-partner" target="_blank"><img src="packages/appium/docs/overrides/assets/images/sponsor-logo-sauce.png" width="250"/></a>
|
||||
|
||||
## Gold Sponsors
|
||||
|
||||
<a href="https://opencollective.com/appium" target="_blank"><img src="https://opencollective.com/appium/tiers/gold-sponsor.svg?avatarHeight=100&button=false"/></a>
|
||||
|
||||
[Become a Gold Sponsor](https://opencollective.com/appium/contribute/gold-sponsor-72877/checkout?interval=month&amount=500&contributeAs=me)
|
||||
|
||||
## Silver Sponsors
|
||||
|
||||
<a href="https://opencollective.com/appium" target="_blank"><img src="https://opencollective.com/appium/tiers/silver-sponsor.svg?avatarHeight=80&button=false"/></a>
|
||||
|
||||
[Become a Silver Sponsor](https://opencollective.com/appium/contribute/silver-sponsor-72876/checkout?interval=month&amount=250&contributeAs=me)
|
||||
|
||||
## Bronze Sponsors
|
||||
|
||||
<a href="https://opencollective.com/appium" target="_blank"><img src="https://opencollective.com/appium/tiers/sponsors.svg?avatarHeight=60&button=false"/></a>
|
||||
|
||||
[Become a Bronze Sponsor](https://opencollective.com/appium/contribute/sponsors-70690/checkout?interval=month&amount=100&contributeAs=me)
|
||||
Please check [Sponsors & Backers](https://appium.io/docs/en/latest/sponsors/)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
This documentation is a note for the opencollective payout.
|
||||
|
||||
1. Select `Submit expense`
|
||||
|
||||
<img width="200" alt="Screenshot 2024-09-17 at 11 04 32 PM" src="https://github.com/user-attachments/assets/5d598a46-8aa3-41e0-aadc-ce3f34b10f6b">
|
||||
|
||||
2. Select `Invoice`
|
||||
3. Type proper account name in `Who is being paid for this expense?`
|
||||
- The form depends on the target user
|
||||
4. Select `Next`
|
||||
5. Input expense info and complete the form. Then, the user will recieve the expense info.
|
||||
- Expense title: `<year-month> contribution payout`
|
||||
- e.g. `2024-07 contribution payout`
|
||||
- Description in "Set invoice details"
|
||||
- for TCs:
|
||||
- `<year-month> contribution as a TC https://github.com/appium/appium/blob/master/GOVERNANCE.md#the-technical-committee and maintaining Appium project itself (development, review etc)`
|
||||
- i.e. `2024-07 contribution as a TC https://github.com/appium/appium/blob/master/GOVERNANCE.md#the-technical-committee and maintaining Appium project itself (development, review etc)`
|
||||
- for individuals
|
||||
- `PR contribution: <PRs>` for PRs. `Community contribution in Q&A forum at https://discuss.appium.io/` for appium forums
|
||||
- E.g.
|
||||
- `PR contribution: https://github.com/appium/dotnet-client/pull/810, https://github.com/appium/dotnet-client/pull/808`
|
||||
- `PR contribution: https://github.com/appium/java-client/pull/2206, https://github.com/appium/java-client/pull/2203 and a few PRs`
|
||||
- `Community contribution in Q&A forum at https://discuss.appium.io/`
|
||||
- Amount
|
||||
- Type the amount in `USD`
|
||||
6. Approve each expense after getting response for each expense
|
||||
|
||||
<img width="500" alt="Screenshot 2024-09-11 at 8 40 35 PM" src="https://github.com/user-attachments/assets/462cda69-1ce7-458c-b319-dda87cf10d65">
|
||||
Generated
+2464
-3091
File diff suppressed because it is too large
Load Diff
+29
-26
@@ -38,12 +38,15 @@
|
||||
"clean:interactive": "git clean -d -x -i",
|
||||
"clean:force": "git clean -d -x -f",
|
||||
"clean:workspaces": "lerna run clean || true",
|
||||
"crowdin-sync-docs-translations": "node ./scripts/crowdin-sync-docs-translations.mjs",
|
||||
"crowdin-update-docs": "node ./scripts/crowdin-update-docs-resources.mjs",
|
||||
"dev": "run-s build:compile \"build:workspaces\" \"build:compile -- --watch\"",
|
||||
"dev:docs": "npm run -w packages/appium dev:docs",
|
||||
"docs": "npm run -w packages/appium build:docs",
|
||||
"docs:preview": "npm run -w packages/appium build:docs:preview",
|
||||
"docs:publish": "npm run -w packages/appium publish:docs",
|
||||
"doctor": "node ./packages/doctor",
|
||||
"doctor": "node ./scripts/doctor-stub.mjs",
|
||||
"install-docs-deps": "npm run -w packages/appium install-docs-deps",
|
||||
"lint": "eslint .",
|
||||
"lint:ci": "eslint --quiet .",
|
||||
"lint:fix": "run-s \"lint -- --fix\"",
|
||||
@@ -83,53 +86,53 @@
|
||||
"devDependencies": {
|
||||
"@colors/colors": "1.6.0",
|
||||
"@tsconfig/node14": "14.1.2",
|
||||
"@types/chai": "4.3.17",
|
||||
"@types/chai-as-promised": "7.1.8",
|
||||
"@types/diff": "5.2.1",
|
||||
"@types/mocha": "10.0.7",
|
||||
"@types/node": "20.14.14",
|
||||
"@types/chai": "5.0.1",
|
||||
"@types/chai-as-promised": "8.0.1",
|
||||
"@types/diff": "6.0.0",
|
||||
"@types/mocha": "10.0.10",
|
||||
"@types/node": "22.10.1",
|
||||
"@types/semver": "7.5.8",
|
||||
"@types/sinon": "17.0.3",
|
||||
"@types/sinon-chai": "3.2.12",
|
||||
"@types/sinon-chai": "4.0.0",
|
||||
"@types/source-map-support": "0.5.10",
|
||||
"@types/teen_process": "2.0.4",
|
||||
"@types/ws": "8.5.12",
|
||||
"@types/yargs": "17.0.32",
|
||||
"@types/ws": "8.5.13",
|
||||
"@types/yargs": "17.0.33",
|
||||
"@typescript-eslint/eslint-plugin": "7.18.0",
|
||||
"@typescript-eslint/parser": "7.18.0",
|
||||
"asyncbox": "3.0.0",
|
||||
"chai": "5.1.1",
|
||||
"chai-as-promised": "8.0.0",
|
||||
"chai": "5.1.2",
|
||||
"chai-as-promised": "8.0.1",
|
||||
"conventional-changelog-conventionalcommits": "7.0.2",
|
||||
"cpy-cli": "5.0.0",
|
||||
"eslint": "8.57.0",
|
||||
"eslint": "8.57.1",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
"eslint-find-rules": "4.1.0",
|
||||
"eslint-import-resolver-typescript": "3.6.1",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-find-rules": "4.2.0",
|
||||
"eslint-import-resolver-typescript": "3.7.0",
|
||||
"eslint-plugin-import": "2.31.0",
|
||||
"eslint-plugin-mocha": "10.5.0",
|
||||
"eslint-plugin-promise": "6.6.0",
|
||||
"finalhandler": "1.2.0",
|
||||
"finalhandler": "1.3.1",
|
||||
"get-port": "5.1.1",
|
||||
"json-schema-to-typescript": "15.0.0",
|
||||
"lerna": "8.1.7",
|
||||
"json-schema-to-typescript": "15.0.3",
|
||||
"lerna": "8.1.9",
|
||||
"log-symbols": "4.1.0",
|
||||
"midnight-smoker": "8.0.0",
|
||||
"mjpeg-consumer": "2.0.0",
|
||||
"mjpeg-server": "0.3.1",
|
||||
"mocha": "10.7.0",
|
||||
"npm-run-all2": "6.2.2",
|
||||
"prettier": "3.3.3",
|
||||
"mocha": "11.0.1",
|
||||
"npm-run-all2": "6.2.6",
|
||||
"prettier": "3.4.2",
|
||||
"rewiremock": "3.14.5",
|
||||
"rimraf": "5.0.10",
|
||||
"serve-static": "1.15.0",
|
||||
"sinon": "18.0.0",
|
||||
"serve-static": "1.16.2",
|
||||
"sinon": "19.0.2",
|
||||
"sync-monorepo-packages": "1.0.2",
|
||||
"ts-node": "10.9.2",
|
||||
"tsd": "0.31.1",
|
||||
"typescript": "5.5.4",
|
||||
"tsd": "0.31.2",
|
||||
"typescript": "5.7.2",
|
||||
"validate.js": "0.13.1",
|
||||
"webdriverio": "8.40.0",
|
||||
"webdriverio": "8.40.6",
|
||||
"ws": "8.18.0",
|
||||
"yaml-js": "0.3.1"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,106 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.13.1](https://github.com/appium/appium/compare/appium@2.13.0...appium@2.13.1) (2024-12-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **docutils:** update dependency lilconfig to v3.1.3 ([#20803](https://github.com/appium/appium/issues/20803)) ([93fa5cc](https://github.com/appium/appium/commit/93fa5ccb06eb5089bb3e8a8d9e67dad7f4446a0a))
|
||||
* **support:** update dependency axios to v1.7.9 ([#20811](https://github.com/appium/appium/issues/20811)) ([69f100a](https://github.com/appium/appium/commit/69f100ad3e12030708dee4b8a74005dd41976e37))
|
||||
* **support:** update dependency teen_process to v2.2.2 ([#20808](https://github.com/appium/appium/issues/20808)) ([c91683f](https://github.com/appium/appium/commit/c91683f50feea937ff8568eab6366465a6cf9a3e))
|
||||
* **types:** update dependency type-fest to v4.30.0 ([#20802](https://github.com/appium/appium/issues/20802)) ([8590432](https://github.com/appium/appium/commit/8590432955eb7663e35847db541b9ead3f845a36))
|
||||
|
||||
|
||||
|
||||
## [2.13.0](https://github.com/appium/appium/compare/appium@2.12.2...appium@2.13.0) (2024-12-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **base-driver:** Allow to prefix feature names with automation names ([#20793](https://github.com/appium/appium/issues/20793)) ([942057d](https://github.com/appium/appium/commit/942057d26cbf51539f34b6b7ff8a3c1d07821687))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **types:** update dependency type-fest to v4.29.1 ([#20795](https://github.com/appium/appium/issues/20795)) ([6ba31fe](https://github.com/appium/appium/commit/6ba31fe5766f69cb010a4cac81233f4c3cbcf80f))
|
||||
|
||||
|
||||
|
||||
## [2.12.2](https://github.com/appium/appium/compare/appium@2.12.1...appium@2.12.2) (2024-11-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **appium:** correctly handle git/github install types (fix [#20781](https://github.com/appium/appium/issues/20781)) ([#20788](https://github.com/appium/appium/issues/20788)) ([522f05d](https://github.com/appium/appium/commit/522f05d25ecdf65e2ae22bd7830a250346fc5752))
|
||||
* **appium:** update dependency winston to v3.16.0 ([275da08](https://github.com/appium/appium/commit/275da089e45daba030fbc53d3943e2a9929b27e4))
|
||||
* **appium:** update dependency winston to v3.17.0 ([#20736](https://github.com/appium/appium/issues/20736)) ([f91d8c8](https://github.com/appium/appium/commit/f91d8c8812b77c8739b23d4d49c15a44e19cbcbe))
|
||||
* **docutils:** update dependency yaml to v2.6.1 ([#20762](https://github.com/appium/appium/issues/20762)) ([a5389e6](https://github.com/appium/appium/commit/a5389e648af22570a55e70de71c159874362ffd9))
|
||||
* **support:** update dependency axios to v1.7.8 ([#20778](https://github.com/appium/appium/issues/20778)) ([f9920e2](https://github.com/appium/appium/commit/f9920e2c1b02e3587e5d5fa00ac59055ab57fedd))
|
||||
* **types:** update dependency type-fest to v4.27.0 ([#20754](https://github.com/appium/appium/issues/20754)) ([d6b4079](https://github.com/appium/appium/commit/d6b40797d387711df94c29984af91308da27f92b))
|
||||
* **types:** update dependency type-fest to v4.28.0 ([#20775](https://github.com/appium/appium/issues/20775)) ([a25d8f1](https://github.com/appium/appium/commit/a25d8f129c8baf76ab40ce3b8d053f7da77f14b3))
|
||||
* **types:** update dependency type-fest to v4.29.0 ([#20783](https://github.com/appium/appium/issues/20783)) ([b6aa5ac](https://github.com/appium/appium/commit/b6aa5ace6e54709dba54bc62a902d91851ab7ef1))
|
||||
|
||||
|
||||
|
||||
## [2.12.1](https://github.com/appium/appium/compare/appium@2.12.0...appium@2.12.1) (2024-10-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **docutils:** restore support for Python <3.12 ([#20675](https://github.com/appium/appium/issues/20675)) ([00cd1b4](https://github.com/appium/appium/commit/00cd1b4b0fcf24d0014dac780223e5866f39c9ce))
|
||||
* **support:** update definitelytyped ([#20691](https://github.com/appium/appium/issues/20691)) ([846dd52](https://github.com/appium/appium/commit/846dd5288608d886f924d2791291475c956d53f7))
|
||||
|
||||
|
||||
|
||||
## [2.12.0](https://github.com/appium/appium/compare/appium@2.11.5...appium@2.12.0) (2024-10-15)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **appium:** Make server graceful shutdown timeout configurable via command line args ([#20641](https://github.com/appium/appium/issues/20641)) ([5661888](https://github.com/appium/appium/commit/56618886ed007df3c28ce98beb4ff91bc47da2a2))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **appium:** update dependency winston to v3.15.0 ([ab12235](https://github.com/appium/appium/commit/ab12235483262a1c5a1dd8a32b1792a4b096bfc6))
|
||||
* **docutils:** support Python 3.12+ ([#20666](https://github.com/appium/appium/issues/20666)) ([8d7cec9](https://github.com/appium/appium/commit/8d7cec96d8df60644493a7e2f735b4bb0d3783be))
|
||||
* **docutils:** update dependency yaml to v2.6.0 ([ed6c6dd](https://github.com/appium/appium/commit/ed6c6dd5441e26fc1eb58de9b78def49d930a128))
|
||||
* **execute-driver-plugin:** update dependency webdriverio to v8.40.6 ([796ca9f](https://github.com/appium/appium/commit/796ca9f98f69616b9c890325bbfb0c573a8bc765))
|
||||
|
||||
|
||||
|
||||
## [2.11.5](https://github.com/appium/appium/compare/appium@2.11.4...appium@2.11.5) (2024-09-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **appium:** Return hostname as web socket url for BiDi if a broadcast address is assigned to the server ([#20603](https://github.com/appium/appium/issues/20603)) ([f0de55d](https://github.com/appium/appium/commit/f0de55da0da2fc0305876a948704c1f0a2a5990f))
|
||||
|
||||
|
||||
|
||||
## [2.11.4](https://github.com/appium/appium/compare/appium@2.11.3...appium@2.11.4) (2024-09-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **appium:** Fix the condition for secure websocket ([#20497](https://github.com/appium/appium/issues/20497)) ([efdb1ce](https://github.com/appium/appium/commit/efdb1ce6ce1de5120f2f35ebe84abfa73ed5198a))
|
||||
* **appium:** update dependency @sidvind/better-ajv-errors to v3 ([#20552](https://github.com/appium/appium/issues/20552)) ([0ee7716](https://github.com/appium/appium/commit/0ee7716cf0644cfc6795f0949d8253d4c0b36597))
|
||||
* **appium:** update dependency winston to v3.14.2 ([#20465](https://github.com/appium/appium/issues/20465)) ([893fc04](https://github.com/appium/appium/commit/893fc040e16ec07c83d12c7c89180d962b0f6e68))
|
||||
* **base-driver:** Add a server flag to check if it operates a secure protocol ([#20449](https://github.com/appium/appium/issues/20449)) ([622b245](https://github.com/appium/appium/commit/622b245ea38793280d9785a59a0416ce025862fe))
|
||||
* **docutils:** update dependency yaml to v2.5.1 ([750872a](https://github.com/appium/appium/commit/750872af4756d2efcd19fe98762f82ecaa59d59a))
|
||||
* **execute-driver-plugin:** update dependency webdriverio to v8.40.3 ([4608563](https://github.com/appium/appium/commit/46085635a92c3a2b2b1b3ecf3966a174248a2829))
|
||||
* **execute-driver-plugin:** update dependency webdriverio to v8.40.5 ([dcb6de2](https://github.com/appium/appium/commit/dcb6de22eaabdcea2517cd9b7db120d681f0e38e))
|
||||
* **support:** update dependency axios to v1.7.4 ([d17d022](https://github.com/appium/appium/commit/d17d0222245ab94a78e578c0398734e65a89ba68))
|
||||
* **support:** update dependency axios to v1.7.5 ([fedabb1](https://github.com/appium/appium/commit/fedabb1fdc7af10f9e4b06ea23815c4bc7c6bf5e))
|
||||
* **support:** update dependency axios to v1.7.7 ([7fe67a2](https://github.com/appium/appium/commit/7fe67a286a15a917ce3b1b47a08e982e65bbd9e4))
|
||||
* **types:** update dependency type-fest to v4 ([#20467](https://github.com/appium/appium/issues/20467)) ([482a1f7](https://github.com/appium/appium/commit/482a1f7bbfbf6478ee09bb1668b830ddbf13b143))
|
||||
* **types:** update dependency type-fest to v4 ([#20471](https://github.com/appium/appium/issues/20471)) ([9a66f48](https://github.com/appium/appium/commit/9a66f4800141cc86c90d58ca1103bab0066081bc))
|
||||
* **types:** update dependency type-fest to v4 ([#20548](https://github.com/appium/appium/issues/20548)) ([5b8cb76](https://github.com/appium/appium/commit/5b8cb76ea3cda75095e79c91539be73feeadf869))
|
||||
* **types:** update dependency type-fest to v4.26.0 ([#20511](https://github.com/appium/appium/issues/20511)) ([8f20c97](https://github.com/appium/appium/commit/8f20c973f4a6d3380163b6afd7f113808453a62d))
|
||||
|
||||
|
||||
|
||||
## [2.11.3](https://github.com/appium/appium/compare/appium@2.11.2...appium@2.11.3) (2024-08-07)
|
||||
|
||||
|
||||
|
||||
@@ -9,11 +9,15 @@
|
||||
Cross-platform test automation for native, hybrid, mobile web and desktop apps.
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](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/)
|
||||
|
||||
</div>
|
||||
|
||||
***
|
||||
|
||||
<p align="center"><b>
|
||||
@@ -21,7 +25,7 @@
|
||||
<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://github.com/appium/appium/blob/master/ROADMAP.md">Roadmap</a> |
|
||||
<a href="https://appium.io/docs/en/latest/contributing/">Contributing Guide</a> |
|
||||
<a href="https://discuss.appium.io">Discussion Forum</a>
|
||||
</b></p>
|
||||
|
||||
@@ -190,11 +194,6 @@ rely on. [Become a sponsor](https://opencollective.com/appium) via our OpenColle
|
||||
Appium is incredibly grateful to our Development and Strategic Partners for their sustained
|
||||
contribution of project development and leadership!
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.headspin.io/solutions/appium-mobile-test-automation"><img src="packages/appium/docs/overrides/assets/images/sponsor-logo-headspin.png"
|
||||
width="275" alt="HeadSpin" /></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.browserstack.com/browserstack-appium?utm_campaigncode=701OW00000AoUTQYA3&utm_medium=partnered&utm_source=appium">
|
||||
<picture>
|
||||
@@ -212,7 +211,7 @@ width="300" alt="Sauce Labs" /></a>
|
||||
|
||||
### Other Sponsors
|
||||
|
||||
A full list of sponsors is available at our [Sponsors page](SPONSORS.md).
|
||||
A full list of sponsors is available at our [Sponsors page](https://appium.io/docs/en/latest/sponsors/).
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ plugins:
|
||||
'reference/commands/images-plugin.md': 'commands/images-plugin.md'
|
||||
'reference/commands/relaxed-caps-plugin.md': 'commands/relaxed-caps-plugin.md'
|
||||
'reference/commands/universal-xml-plugin.md': 'commands/universal-xml-plugin.md'
|
||||
'contributing/config-system.md': 'developing/config-system.md'
|
||||
'contributing/develop.md': 'contributing.md'
|
||||
|
||||
extra_css:
|
||||
- assets/stylesheets/extra.css
|
||||
|
||||
@@ -21,6 +21,4 @@ environment variables that the Appium server understands:
|
||||
|`APPIUM_OMIT_PEER_DEPS`|Adds `--omit=peer` to all the NPM commands run internally by Appium. Mostly an internal feature.|
|
||||
|`APPIUM_APPS_CACHE_MAX_AGE`|Allows to set the maximum age (in minutes) for [cached applications](../guides/caching.md). The default value is `60 * 24` (24 hours). Do not set it to a lower number than the duration of a single session startup.|
|
||||
|`APPIUM_APPS_CACHE_MAX_ITEMS`|Allows to set the maximum amount of [cached applications](../guides/caching.md). The default value is `1024`. Do not set it to a lower number than the amount of apps in all parallel sessions per process.|
|
||||
|`APPIUM_APPS_CACHE_IGNORE_URL_QUERY`| If the above option is enabled then the 'search' part of the app URL will be cut off from cache keys. See the corresponding
|
||||
[feature request](https://discuss.appium.io/t/regarding-app-caching-when-using-aws-s3-presigned-urls/42713)
|
||||
for more details. Disabled by default.|
|
||||
|`APPIUM_APPS_CACHE_IGNORE_URL_QUERY`| If the above option is enabled then the 'search' part of the app URL will be cut off from cache keys. See the corresponding [feature request](https://discuss.appium.io/t/regarding-app-caching-when-using-aws-s3-presigned-urls/42713) for more details. Disabled by default.|
|
||||
|
||||
@@ -24,5 +24,10 @@ will only install the missing extensions.
|
||||
Refer to the [Ecosystem documentation](../ecosystem/index.md) to learn more about the extensions
|
||||
listed above.
|
||||
|
||||
This commands also supports the functionality that allows to fully reset your Appium server
|
||||
deployment if you experience various configuration issues,
|
||||
for example, due to a failed upgrade attempt from an older Appium version, on server startup.
|
||||
By running `appium setup reset` the server would uninstall all installed drivers, plugins and their related manifest files from the currently used Appium home folder.
|
||||
|
||||
[^1]: Only installed if the host machine is running macOS.
|
||||
[^2]: Only installed if the host machine is running Windows.
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
---
|
||||
hide:
|
||||
- navigation
|
||||
|
||||
title: Contributing to Appium
|
||||
---
|
||||
|
||||
The Appium project would not exist without the many contributions of code, documentation,
|
||||
maintenance, and support from companies and volunteers. As such, we welcome contributions!
|
||||
|
||||
There are a lot of different ways to help the project - see below for everything you can do and the
|
||||
processes to follow for each contribution method. Note that no matter how you contribute, your
|
||||
participation is governed by our [Code of Conduct](https://github.com/appium/appium/blob/master/CONDUCT.md).
|
||||
|
||||
## Join the Discussion Forum
|
||||
|
||||
You don't need to know the internals of Appium to be able to contribute! If you have experience with
|
||||
using Appium and feel like sharing your knowledge with others, consider helping out users on the
|
||||
Appium forums at [discuss.appium.io](https://discuss.appium.io/). Hop on over and see if there are
|
||||
any questions that you can answer.
|
||||
|
||||
## Report Bugs or Feature Requests
|
||||
|
||||
If you've encountered a bug, or have a cool feature in mind that you think Appium should support,
|
||||
make sure to let us know at our [GitHub issue tracker](https://github.com/appium/appium/issues).
|
||||
Please use the appropriate issue form template when creating your issue.
|
||||
|
||||
## Triage Issues
|
||||
|
||||
In addition to creating issues, you can also help us investigate already reported issues. All you
|
||||
need is enough familiarity with Appium to try and reproduce bugs.
|
||||
|
||||
You can get started by checking our [GitHub issue tracker](https://github.com/appium/appium/issues)
|
||||
for issues with labels such as `Needs Triage` or `Needs Info`, and leaving relevant comments:
|
||||
|
||||
- If the issue is a duplicate, drop a link to the original issue
|
||||
- If the user has not provided enough information (such as Appium logs), ask them for more details
|
||||
- If you can reproduce the problem on your own environment, provide all the information that you think
|
||||
would help us track down the cause of the issue
|
||||
|
||||
For further information on triaging Appium issues (for any Appium project repository), please contact
|
||||
any member of the [Technical Committee](https://github.com/appium/appium/blob/master/GOVERNANCE.md#the-technical-committee).
|
||||
|
||||
## Contribute Code
|
||||
|
||||
We are always open to pull requests for improving the Appium code or documentation!
|
||||
|
||||
!!! info
|
||||
|
||||
Developer information may not be kept up to date as frequently as user-facing information, or
|
||||
it may be most relevant in its current form on the online repository, not in this published
|
||||
version. Make sure to check the repo or discuss with maintainers. We would be glad to help
|
||||
new contributors get started!
|
||||
|
||||
Start by cloning the repository (we recommend [forking](https://github.com/appium/appium/fork)
|
||||
it first):
|
||||
```sh
|
||||
git clone https://github.com/appium/appium.git
|
||||
cd appium
|
||||
```
|
||||
|
||||
!!! info
|
||||
|
||||
If you are VS Code user, you can easily check out the project using [Runme](https://runme.dev/api/runme?repository=https%3A%2F%2Fgithub.com%2Fappium%2Fappium.git&fileToOpen=packages%2Fappium%2Fdocs%2Fen%2Fcontributing%2Findex.md).
|
||||
|
||||
Install dependencies:
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
From here on there are several things you can do.
|
||||
|
||||
Build the project:
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
Build the project and watch for changes:
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Start the locally built Appium server:
|
||||
```sh
|
||||
npm start
|
||||
```
|
||||
|
||||
Run various tests:
|
||||
```sh
|
||||
npm run lint
|
||||
npm run test:unit
|
||||
npm run test:types
|
||||
npm run test:smoke
|
||||
npm run test:e2e
|
||||
npm run test:quick # unit and types
|
||||
npm run test:slow # everything
|
||||
```
|
||||
|
||||
You can also run tests for specific workspaces, e.g.:
|
||||
|
||||
```sh
|
||||
export APPIUM_WORKSPACE=@appium/base-driver
|
||||
npm run test:unit -w $APPIUM_WORKSPACE
|
||||
```
|
||||
|
||||
### Documentation
|
||||
|
||||
The documentation for this project is [available in the project repository itself](https://github.com/appium/appium/tree/master/packages/appium/docs).
|
||||
It is contained in Markdown files, which are built by our documentation system in the
|
||||
`@appium/docutils` module. This module is based on [MkDocs](https://www.mkdocs.org/) and therefore
|
||||
requires [Python](https://www.python.org/) to be installed on your system.
|
||||
|
||||
Install Python dependencies:
|
||||
```sh
|
||||
npm run install-docs-deps
|
||||
```
|
||||
|
||||
After making your changes, you can run the documentation server in dev mode:
|
||||
```sh
|
||||
npm run dev:docs
|
||||
```
|
||||
|
||||
You can then view the documentation at `http://127.0.0.1:8000/docs/en`.
|
||||
|
||||
## Translating Appium Documentation
|
||||
|
||||
The process of Appium documents localization into languages other than English is automated and is done via
|
||||
the [Crowdin Translations Management System](https://crowdin.com). Do not edit any translated documents
|
||||
directly in the GitHub Appium repository as they are going to be replaced with ones exported from Crowdin
|
||||
during an upcoming sync.
|
||||
|
||||
### Where To Start
|
||||
|
||||
If you would like to contribute to the translation of Appium documents into your language then simply join
|
||||
the translators group for the [Appium Documentation](https://crowdin.com/project/appium-documentation)
|
||||
Crowdin project, and start translating documents there. If you see that your language is missing from
|
||||
the list of available Crowdin languages then simply let us know by creating an
|
||||
[issue](https://github.com/appium/appium/issues).
|
||||
|
||||
### Source Language Updates
|
||||
|
||||
Changes in documents are synchronized to Crowdin automatically via the `Update Crowdin English Docs` GitHub action.
|
||||
This action is triggered automatically as soon as there are any changes under `packages/appium/docs/en/**.md`
|
||||
or `packages/appium/docs/mkdocs-en.yml`.
|
||||
|
||||
### Fetching Translated Documents
|
||||
|
||||
In order to fetch translated files from Crowdin to the GitHub repository it is necessary to trigger
|
||||
the `Sync Crowdin Docs Translations` action. This action should also automatically create a PR with
|
||||
corresponding translated resources included.
|
||||
@@ -1,90 +0,0 @@
|
||||
---
|
||||
title: Contributing Code
|
||||
---
|
||||
|
||||
To contribute to the Appium code base make sure to check out the Git repository.
|
||||
|
||||
!!! info
|
||||
|
||||
If you are VS Code user you can easily check out the project using [Runme](https://runme.dev/api/runme?repository=https%3A%2F%2Fgithub.com%2Fappium%2Fappium.git&fileToOpen=packages%2Fappium%2Fdocs%2Fen%2Fcontributing%2Findex.md).
|
||||
|
||||
It is advised to [fork](https://github.com/appium/appium/fork) before cloning it to your system.
|
||||
|
||||
```sh
|
||||
export GITHUB_USERNAME=<your-username>
|
||||
git clone git@github.com:$GITHUB_USERNAME/appium.git
|
||||
```
|
||||
|
||||
After cloning you can go ahead and install the project dependencies:
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
From here on there are several things you can do.
|
||||
|
||||
### Watch Files
|
||||
|
||||
When developing Appium code we have to watch all JavaScript and TypeScript files to re-compile them after every change. You can run this watch process via:
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Start Appium in Dev-Mode
|
||||
|
||||
To test your changes you can run Appium in dev mode via:
|
||||
|
||||
```sh
|
||||
npm start
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
The project maintains a set of different test variations you can run to verify the quality of the code.
|
||||
|
||||
#### Linting
|
||||
|
||||
Appium uses [`eslint`](https://eslint.org/) for static code analysis and linting. You can run these checks via:
|
||||
|
||||
```sh
|
||||
npm run lint
|
||||
```
|
||||
|
||||
#### Unit
|
||||
|
||||
```sh
|
||||
npm run test:unit
|
||||
```
|
||||
|
||||
You can also run tests for specific workspaces, e.g.:
|
||||
|
||||
```sh
|
||||
export APPIUM_WORKSPACE=@appium/doctor
|
||||
npm run test:unit -w $APPIUM_WORKSPACE
|
||||
```
|
||||
|
||||
#### Smoke and E2E
|
||||
|
||||
```sh
|
||||
npm run test:slow
|
||||
```
|
||||
|
||||
### Deploy Docs Locally
|
||||
|
||||
Our documentation system uses [MKDocs](https://www.mkdocs.org/) and therefore requires [Python](https://www.python.org/) to be installed on your system. You can run the docs by:
|
||||
|
||||
```sh
|
||||
# installing needed Python dependencies
|
||||
pip install -r packages/docutils/requirements.txt
|
||||
# build the project
|
||||
npm run build
|
||||
# run dev server
|
||||
npm run dev:docs
|
||||
```
|
||||
|
||||
You should be able to view the page at `http://127.0.0.1:8000/docs/en`:
|
||||
|
||||
```sh
|
||||
open http://127.0.0.1:8000/docs/en
|
||||
```
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Contributing to Appium
|
||||
---
|
||||
|
||||
Appium is open source, available under an Apache 2.0 license. Appium's copyright is held by the
|
||||
[OpenJS Foundation](https://openjsf.org), and Appium receives contributions from many companies
|
||||
across several software industries, regardless of their competitive status. (3rd-party drivers and
|
||||
plugins are available under the licenses provided by their authors.)
|
||||
|
||||
As such, we welcome contributions! The project moves forward in relation to the investment of
|
||||
contributions of code, documentation, maintenance, and support from companies and volunteers.
|
||||
|
||||
This section of Appium's documentation is for those who are interested in contributing to Appium's
|
||||
development. It contains developer overviews, guides, and notes. Use the navigation menu to find
|
||||
a specific topic. All the information in these guides assumes in-depth familiarity with Appium
|
||||
already.
|
||||
|
||||
!!! warning
|
||||
|
||||
Developer information may not be kept up to date as frequently as user-facing information, or
|
||||
it may be most relevant in its current form on the online repository, not in this published
|
||||
version. Always be sure to check the repo or discuss with maintainers. We're always happy to
|
||||
help new contributors get started!
|
||||
|
||||
## Ways to Contribute
|
||||
|
||||
The project offers a variety of ways to contribute, e.g.:
|
||||
|
||||
- [contributing code](./develop.md)
|
||||
- improving documentation
|
||||
- creating educational content (blog posts, tutorials, videos, etc.)
|
||||
- spreading the good word about the project (e.g. via Twitter)
|
||||
- filing bugs if you discover them while using Appium
|
||||
- making feature requests if you are missing something in the project or help triaging bugs
|
||||
- supporting users in the [Appium forum](https://discuss.appium.io/)
|
||||
@@ -222,30 +222,23 @@ async handle(next, driver, cmdName, ...args) {
|
||||
}
|
||||
```
|
||||
|
||||
### Work around driver proxies
|
||||
### Working with driver proxies
|
||||
|
||||
There is a bit of a gotcha with handling Appium commands. Appium drivers have the ability to turn
|
||||
on a special 'proxy' mode, wherein the Appium server process takes a look at incoming URLs, and
|
||||
decides whether to forward them on to some upstream WebDriver server. It could happen that
|
||||
a command which a plugin wants to handle is designated as a command which is being proxied to an
|
||||
upstream server. In this case, we run into a problem, because the plugin never gets a chance to
|
||||
handle that command! For this reason, plugins can implement a special member function called
|
||||
`shouldAvoidProxy`, which takes the following parameters:
|
||||
|
||||
1. `method` - string denoting HTTP method (`GET`, `POST`, etc...)
|
||||
2. `route` - string denoting the requested resource, for example `/session/8b3d9aa8-a0ca-47b9-9ab7-446e818ec4fc/source`
|
||||
3. `body` - optional value of any type representing the WebDriver request body
|
||||
|
||||
These parameters define an incoming request. If you want to handle a command in your plugin which
|
||||
would normally be proxied directly through a driver, you could disable or 'avoid' proxying the
|
||||
request, and instead have the request fall into the typical Appium command execution flow (and
|
||||
thereby your own command function). To avoid proxying a request, just return `true` from
|
||||
`shouldAvoidProxy`. Some examples of how this method is used are in the [Universal XML
|
||||
plugin](https://github.com/appium/appium/blob/master/packages/universal-xml/lib/plugin.js) (where
|
||||
we want to avoid proxying the `getPageSource` command, or in the [Images
|
||||
plugin](https://github.com/appium/appium/blob/master/packages/images-plugin/lib/plugin.js) (where
|
||||
we want to conditionally avoid proxying any command if it looks like it contains an image element).
|
||||
upstream server. In this case, we might run into a problem, because the plugin never gets a chance to
|
||||
handle that command! The way Appium handles this is as follows:
|
||||
|
||||
1. When a command comes in, before deciding whether to proxy the command, the main protocol handler
|
||||
checks to see whether a plugin would handle the command.
|
||||
2. If a plugin would *not* handle the command--all proceeds as normal, and the request is either
|
||||
proxied or not, based on the driver's proxy mode.
|
||||
3. If a plugin *would* handle the command, then the proxy behavior is skipped for the time being,
|
||||
and wrapped up as the `next` function sent to the plugin. So if you have a command handler in
|
||||
your plugin, and you want to be sure that the default driver proxying *does* take place, then
|
||||
simply `await next()` instead of (or in addition to) whatever your plugin handler is doing.
|
||||
|
||||
### Throw WebDriver-specific errors
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@ These drivers are not maintained by the Appium team and can be used to target ad
|
||||
|[Tizen](https://github.com/Samsung/appium-tizen-driver)|`--source=npm appium-tizen-driver`|Android|Native|Community / Samsung|
|
||||
|[TizenTV](https://github.com/headspinio/appium-tizen-tv-driver)|`--source=npm appium-tizen-tv-driver`|Samsung TV|Web|HeadSpin|
|
||||
|[Youi](https://github.com/YOU-i-Labs/appium-youiengine-driver)|`--source=npm appium-youiengine-driver`|iOS, Android, macOS, Linux, tvOS|Native|Community / You.i|
|
||||
|[axe UiAutomator2](https://docs.deque.com/devtools-mobile/appium-setup)|`--source=npm @axe-devtools/axe-appium-uiautomator2-driver`|Android|Native|[Deque](https://www.deque.com)|
|
||||
|[axe XCUITest](https://docs.deque.com/devtools-mobile/appium-setup)|`--source=npm @axe-devtools/axe-appium-xcuitest-driver`|iOS|Native|[Deque](https://www.deque.com)|
|
||||
|
||||
!!! note
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ environment before it is merged or published. This tutorial describes how to ach
|
||||
|
||||
## Installation
|
||||
|
||||
- [Check out]((https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally)) the PR locally.
|
||||
- [Check out](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally) the PR locally.
|
||||
There is also an option (although it is less flexible, because you won't be able to easily fetch
|
||||
any changes to this PR later) to simply [download](https://docs.github.com/en/repositories/working-with-files/using-files/downloading-source-code-archives) and unzip the sources
|
||||
locally. If you choose the later option then no `git` tool would be necessary.
|
||||
|
||||
@@ -42,7 +42,7 @@ property in your `package.json` and it will be automatically discovered.
|
||||
Appium will search _up_ the directory tree from the current working directory for one of these
|
||||
files. If it reaches the current user's home directory or filesystem root, it will stop looking.
|
||||
|
||||
To specify a _custom_ location for your config file, use `appium --config-file /path/to/config/file`.
|
||||
To specify a _custom_ location for your config file, use `appium --config /path/to/config/file`.
|
||||
|
||||
#### Configuration File Format
|
||||
|
||||
|
||||
@@ -6,6 +6,11 @@ This document is a guide for those who are using Appium 1 and wish to migrate to
|
||||
contains a list of breaking changes and how to migrate your environments or test suites to ensure
|
||||
compatibility with Appium 2.
|
||||
|
||||
!!! note
|
||||
|
||||
Latest Appium drivers/plugins would have update since we created this documentation
|
||||
because we keep developing the ecosystem.
|
||||
|
||||
## Overview of Appium 2
|
||||
|
||||
Appium 2 is the most major new release of Appium in over 5 years. The changes in Appium 2 are _not_
|
||||
|
||||
@@ -44,6 +44,14 @@ might use. Here is an incomplete list of examples from some of Appium's official
|
||||
|`record_audio`|Allow recording of host machine audio inputs|XCUITest|
|
||||
|`execute_driver_script`| Allows to send a request which has multiple Appium commands.|Execute Driver Plugin|
|
||||
|
||||
## Driver-scope security
|
||||
|
||||
Since Appium server version 2.12.3 there is a possibility to prefix each feature name with the corresponding automationName where it is going to be applied. For example, if you provide the following features to allow:
|
||||
`uiautomator2:adb_shell,xcuitest:get_server_logs,*:record_audio`, then the `adb_shell` would only be allowed
|
||||
for the UiAutomator2 driver, `get_server` - for the XCUITest driver and the `record_audio` one - for
|
||||
all installed drivers. Feature names provided without explicit automation name prefix are equivalent to
|
||||
these having the `*:` prefix. The same feature naming rule applies to the list of denied features.
|
||||
|
||||
## Examples
|
||||
|
||||
To turn on the `get_server_logs` feature for my Appium server, I could start it like this:
|
||||
|
||||
@@ -12,11 +12,13 @@ title: Welcome
|
||||
}
|
||||
</style>
|
||||
|
||||
<div style="text-align:center;width:100%;background-color:#7f56c2" >
|
||||
<h3>
|
||||
Appium Conf 2024 is coming online, 13 September. Have you got something to share with the community? <a style="color:#fcba12" href="https://confengine.com/conferences/appium-conf-2024/proposals?utm_medium=referal&utm_source=appium.io&utm_campaign=launch" target="blank">Submit a proposal</a>
|
||||
</h3>
|
||||
<div style="text-align:center;width:100%;background-color:#ec366d;margin-top:-3em;margin-bottom:2em;">
|
||||
<h3 style="color:#ffffff;padding: 8px;">
|
||||
AppiumConf 2025 is partnering with SeleniumConf<br/> <span style="font-size:0.8em;">March 26-28 in Valencia, Spain. Join us to learn and connect with the community!</span><br/>
|
||||
<a style="color:#fcba12" href="https://seleniumconf.com/" target="_blank">Register Now</a>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div style="text-align: center">
|
||||
<img src="assets/images/appium-logo-horiz.png" style="max-width: 400px;" />
|
||||
</div>
|
||||
@@ -32,11 +34,6 @@ Android TV, Samsung), and more!
|
||||
sponsorship program and contributor compensation scheme <a
|
||||
href="https://github.com/appium/appium/blob/master/GOVERNANCE.md#sponsorship">here</a>)
|
||||
<div class="homepageSponsors">
|
||||
<div class="homepageSponsor">
|
||||
<a href="https://www.headspin.io/solutions/appium-mobile-test-automation">
|
||||
<img src="assets/images/sponsor-logo-headspin.png" style="width: 200px;" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="homepageSponsor">
|
||||
<a href="https://www.browserstack.com/browserstack-appium?utm_campaigncode=701OW00000AoUTQYA3&utm_medium=partnered&utm_source=appium">
|
||||
<img src="assets/images/sponsor-logo-browserstack-dark.png#only-dark" style="width: 220px;" />
|
||||
@@ -63,6 +60,6 @@ Android TV, Samsung), and more!
|
||||
- Read the different [__Guides__](./guides/migrating-1-to-2.md) for a variety of instructions, tips and tricks
|
||||
- Check out various third-party [__Resources__](./resources.md) to explore Appium around the web
|
||||
- For creating your own Appium extensions, see the [__Developer__](./developing/index.md) documentation
|
||||
- For contributions to Appium itself, refer to the [__Contributing__](./contributing/index.md) page
|
||||
- For contributions to Appium itself, refer to the [__Contributing__](./contributing.md) page
|
||||
|
||||
</div>
|
||||
|
||||
@@ -137,8 +137,8 @@ already had well over 1,000 commits.
|
||||
Appium began to grow and mature significantly. In May 2014,
|
||||
we released Appium 1.0, which stood as a milestone in Appium's development.
|
||||
Appium was given
|
||||
[various](http://sauceio.com/index.php/2014/01/appium-selected-as-a-black-duck-open-source-rookie-of-the-year/)
|
||||
[awards](http://sauceio.com/index.php/2014/10/appium-wins-a-bossy-award-from-infoworld/)
|
||||
[various](https://www.prnewswire.com/news-releases/black-duck-announces-black-duck-open-source-rookies-of-the-year-winners-242383341.html)
|
||||
[awards](https://www.infoworld.com/article/2241247/164642-bossie-awards-2014-the-best-open-source-application-development-tools.html)
|
||||
and became the most popular open-source cross-platform mobile automation
|
||||
framework. Stability improved, bugs were prioritized and fixed, and features
|
||||
added. Sauce Labs increased the number of developers it donated to working
|
||||
|
||||
@@ -22,7 +22,7 @@ According to the driver, in addition to a working Appium server, we also need to
|
||||
### Android SDK
|
||||
|
||||
- The easiest way to set up the Android SDK requirements is by downloading [Android Studio](https://developer.android.com/studio).
|
||||
We need to use its SDK manager (_Settings -> Appearance & Behavior -> System Settings -> Android SDK_)
|
||||
We need to use its SDK manager (_Settings -> Languages & Frameworks -> Android SDK_)
|
||||
to download the following items:
|
||||
- Android SDK Platform (select whichever Android platform we want to automate, for example, API level 30)
|
||||
- Android SDK Platform-Tools
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
hide:
|
||||
- navigation
|
||||
- toc
|
||||
|
||||
title: Sponsors & Backers
|
||||
---
|
||||
|
||||
<style>
|
||||
.appium-sponsor-thanks { display: none; }
|
||||
.sponsor-section img { height: 64px; padding-right: 1em; }
|
||||
</style>
|
||||
|
||||
Appium is an Apache-2 licensed open source project whose development is made possible entirely by
|
||||
donations of time and money by individuals and companies who benefit from our software and our
|
||||
mission. If you'd like to join this amazing group and help ensure Appium's continued development
|
||||
and maintenance, you can contribute via [Appium's OpenCollective
|
||||
Hub](https://opencollective.com/appium).
|
||||
|
||||
## Development Partners
|
||||
|
||||
We are very grateful for the support of our Development Partners, who donate Appium development and
|
||||
maintenance as part of their employees' core job duties!
|
||||
|
||||
## Strategic Partners
|
||||
|
||||
We are very grateful for the financial and marketing support of our exclusive Strategic Partners,
|
||||
who contribute a significant ongoing investment of funds to help the project attract and reward
|
||||
contributors!
|
||||
|
||||
<a href="https://www.browserstack.com/browserstack-appium?utm_campaigncode=701OW00000AoUTQYA3&utm_medium=partnered&utm_source=appium">
|
||||
<picture>
|
||||
<source srcset="../assets/images/sponsor-logo-browserstack-dark.png" media="(prefers-color-scheme: dark)"/>
|
||||
<source srcset="../assets/images/sponsor-logo-browserstack-light.png" media="(prefers-color-scheme: light)"/>
|
||||
<img src="../assets/images/sponsor-logo-browserstack-dark.png" width="250" alt="Browserstack"/>
|
||||
</picture>
|
||||
</a>
|
||||
<a style="padding-left: 1em" href="https://saucelabs.com/resources/blog/appium-strategic-partner" target="_blank"><img src="../assets/images/sponsor-logo-sauce.png" width="250"/></a>
|
||||
|
||||
## Gold Sponsors
|
||||
|
||||
<a href="https://opencollective.com/appium" target="_blank"><img src="https://opencollective.com/appium/tiers/gold-sponsor.svg?avatarHeight=100&button=false&random=1"/></a>
|
||||
|
||||
[Become a Gold Sponsor](https://opencollective.com/appium/contribute/gold-sponsor-72877/checkout?interval=month&amount=500&contributeAs=me)
|
||||
|
||||
## Silver Sponsors
|
||||
|
||||
<a href="https://opencollective.com/appium" target="_blank"><img src="https://opencollective.com/appium/tiers/silver-sponsor.svg?avatarHeight=80&button=false&random=1"/></a>
|
||||
|
||||
[Become a Silver Sponsor](https://opencollective.com/appium/contribute/silver-sponsor-72876/checkout?interval=month&amount=250&contributeAs=me)
|
||||
|
||||
## Bronze Sponsors
|
||||
|
||||
<div class="sponsor-section">
|
||||
<a href="https://magicpod.com/" target="_blank"><img src="https://images.opencollective.com/magicpod/722b7e4/avatar/64.png" alt="MagicPod" /></a>
|
||||
<a href="https://route4me.com/" target="_blank"><img src="../assets/images/sponsor-logo-route4me.png" alt="Route Planning and Route Mapping" /></a>
|
||||
<a href="https://webdriver.io/" target="_blank"><img src="https://images.opencollective.com/webdriverio/bbdd6c3/logo/64.png" alt="WebdriverIO" /></a>
|
||||
</div>
|
||||
|
||||
[Become a Bronze Sponsor](https://opencollective.com/appium/contribute/sponsors-70690/checkout?interval=month&amount=100&contributeAs=me)
|
||||
@@ -1,6 +1,3 @@
|
||||
<!---Current latest commit hash in the original English documentation is e4dfa52 --->
|
||||
|
||||
|
||||
---
|
||||
title: Appium 1.xからAppium 2.xへ移行する
|
||||
---
|
||||
@@ -9,19 +6,30 @@ title: Appium 1.xからAppium 2.xへ移行する
|
||||
This document is a guide for those who are using Appium 1.x and wish to migrate to Appium 2.x. It contains a list of breaking changes and how to migrate your environments or test suites to ensure compatibility with Appium 2.0.
|
||||
--->
|
||||
このドキュメントは既にAppium 1.xを利用している人がAppium 2.xに移行するための手引きです。
|
||||
破壊的変更(breaking changes)の一覧や、実行環境・テストコードをAppium 2.0互換にするための方法が含まれます。
|
||||
破壊的変更(breaking changes)の一覧や、実行環境・テストコードをAppium 2.0互換にするための方法が含まれます。
|
||||
|
||||
<!---
|
||||
## Overview of Appium 2.0
|
||||
--->
|
||||
|
||||
<!--
|
||||
!!! note
|
||||
|
||||
Latest Appium drivers/plugins would have update since we created this documentation
|
||||
because we keep developing the ecosystem.
|
||||
--->
|
||||
|
||||
!!! note
|
||||
|
||||
Appiumは継続的に開発されているため、このドキュメントはAppiumドライバーやプラグインに関して情報古い可能性があります。
|
||||
|
||||
## Appium 2.0の概要
|
||||
|
||||
<!---
|
||||
Appium 2.0 is the most major new release of Appium in over 5 years. The changes in Appium 2.0 are _not_ primarily related to changes in automation behaviors for specific platforms. Instead, Appium 2.0 reenvisions Appium as a _platform_ where "drivers" (code projects that introduce support for automation of a given platform) and "plugins" (code projects that allow for overriding, altering, extending, or adding behaviors to Appium) can be easily created and shared.
|
||||
--->
|
||||
|
||||
Appium 2.0は過去5年間におけるAppiumのリリース野中で最も大きなリリースです。Appium 2.0の主要な変更は特定のプラットフォームに対する自動化された動作に関するものでは**ありません**。Appium 2.0はAppiumをドライバー(drivers)(あるプラットフォームに対する自動化を支援するためのプロジェクト)とプラグイン(plugins)(Appiumの動作を上書き、代替、拡張、もしくは追加するためのプロジェクト)という容易に実装、共有できる**仕組みを提供するプラットフォーム**として再考しています。
|
||||
Appium 2.0は過去5年間におけるAppiumのリリース野中で最も大きなリリースです。Appium 2.0の主要な変更は特定のプラットフォームに対する自動化された動作に関するものでは**ありません**。Appium 2.0はAppiumをドライバー(drivers)(あるプラットフォームに対する自動化を支援するためのプロジェクト)とプラグイン(plugins)(Appiumの動作を上書き、代替、拡張、もしくは追加するためのプロジェクト)という容易に実装、共有できる**仕組みを提供するプラットフォーム**として再考しています。
|
||||
|
||||
<!---
|
||||
At the same time, the Appium project is taking the opportunity to remove many old and deprecated bits of functionality.
|
||||
@@ -72,7 +80,7 @@ appium --base-path=/wd/hub
|
||||
You can also set server arguments as [Config file](./config.md) properties.
|
||||
--->
|
||||
|
||||
この設定は[Config file](./config.md)からでも可能です。
|
||||
この設定は[Config file](https://appium.io/docs/en/latest/guides/config/)からでも可能です。
|
||||
|
||||
|
||||
### :bangbang: ドライバーのインストール
|
||||
@@ -81,7 +89,7 @@ You can also set server arguments as [Config file](./config.md) properties.
|
||||
When you installed Appium 1.x, all available drivers would be installed at the same time as the main Appium server. This is no longer the case. Simply installing Appium 2.0 (e.g., by `npm i -g appium`), will install the Appium server only, but no drivers. To install drivers, you must instead use the new [Appium extension CLI](../cli/extensions.md). For example, to install the latest versions of the XCUITest and UiAutomator2 drivers, after installing Appium you would run the following commands:
|
||||
--->
|
||||
|
||||
Appium 1.xをインストールしたとき、全ての入手可能なドライバーは主となるAppiumサーバーと合わせてインストールされていました。Appium 2.0ではそうではありません。Appium 2.0のインストール(例えば `npm i -g appium`)は単にAppiumサーバーのみをインストールし、ドライバーはインストールしません。ドライバーをインストールするためには新しい[Appium拡張コマンドラインインタフェース(Appium extension CLI)](../cli/extensions.md)を使わなければいけません。例えば、最新のXCUITestとUiAutomator2ドライバーをインストールする場合、Appiumをインストールしたのちに次のコマンドを実行する必要があります。
|
||||
Appium 1.xをインストールしたとき、全ての入手可能なドライバーはAppiumサーバーと合わせてインストールされていました。しかしAppium 2.0では異なります。Appium 2.0のインストール(例えば `npm i -g appium` を実行した時)は単にAppiumサーバーのみをインストールし、ドライバーはインストールされません。ドライバーをインストールするためには新しい[Appium拡張コマンドラインインタフェース(Appium extension CLI)](https://appium.io/docs/en/latest/cli/extensions/)を使わなければいけません。例えば、最新のXCUITestとUiAutomator2ドライバーをインストールする場合、Appiumをインストールしたのちに次のコマンドを実行する必要があります。
|
||||
|
||||
```bash
|
||||
appium driver install uiautomator2 # installs the latest driver version
|
||||
@@ -92,110 +100,195 @@ appium driver install xcuitest@4.12.2 # installs a specific driver version
|
||||
At this point, your drivers are installed and ready. There's a lot more you can do with this CLI so be sure to check out the docs on it. If you're running in a CI environment or want to install Appium along with some drivers all in one step, you can do so using some special flags during install, for example:
|
||||
--->
|
||||
|
||||
これにより、ドライバーはインストールされ、利用可能になります。このCLIはいろいろな機能を提供しているので、CLIのドキュメントを確認してみてください。もしCI上であったり、いくつかのドライバーをAppiumと一緒にインストールしたい場合、以下のようなフラグを利用することで実現可能です。
|
||||
これにより、ドライバーがインストールされ、利用可能になります。このCLIはいろいろな機能を提供しているので、CLIのドキュメントを確認してみてください。もしCI上で実行したり、いくつかのドライバーをAppiumと一緒にインストールしたい場合、以下のようなフラグを利用することが可能です。
|
||||
|
||||
```bash
|
||||
npm i -g appium --drivers=xcuitest,uiautomator2
|
||||
```
|
||||
|
||||
<!---
|
||||
This will install Appium and the two drivers for you in one go. Please uninstall any existing Appium 1.x npm packages (with `npm uninstall -g appium`) if you get an installation or startup error.
|
||||
This will install Appium and the two drivers for you in one go. Please uninstall any existing Appium 1.x npm packages (with `npm uninstall -g appium`) if you get an installation or startup error.
|
||||
--->
|
||||
|
||||
これはAppiumと2つのドライバーを一つのコマンドでインストールします。もしセットアップで何らかの問題が発生した場合、既存のAppium 1.xを`npm uninstall -g appium`で削除してみてください。
|
||||
これはAppiumと2つのドライバーを、1つのコマンドでインストールします。もしセットアップで何らかの問題が発生した場合、既存のAppium 1.xを`npm uninstall -g appium`で削除してみてください。
|
||||
|
||||
### :bangbang: Drivers installation path
|
||||
### :bangbang: ドライバーがインストールされるパス
|
||||
|
||||
<!---
|
||||
When you installed Appium 1.x, all available drivers would be installed at the same time as the main Appium server.
|
||||
The path was `/path/to/appium/node_modules`.
|
||||
For example, `appium-webdriveragent` to build WebDriverAgent manually was `/path/to/appium/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent`.
|
||||
|
||||
Appium 2.0 installs such dependencies in `APPIUM_HOME` environment variable. The default path is `~/.appium`.
|
||||
So, the path to `appium-webdriveragent` could be `$APPIUM_HOME/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent` after installing the XCUITest driver package.
|
||||
--->
|
||||
|
||||
### :bangbang: Chromedriver installation flags
|
||||
Appium 1.xをインストールしたとき、全ての入手可能なドライバーは主要なAppiumサーバーと合わせてインストールされていました。
|
||||
そのパスは`/path/to/appium/node_modules`です。
|
||||
例えば、手動でWebDriverAgentをビルドするための`appium-webdriveragent`パッケージは、`/path/to/appium/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent`でした。
|
||||
|
||||
Appium 2.0では、このような依存関係を環境変数 `APPIUM_HOME` にインストールします。デフォルトのパスは `~/.appium` です。
|
||||
そのため、XCUITestドライバーパッケージをインストールすると、`appium-webdriveragent` へのパスは `$APPIUM_HOME/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent` となります。
|
||||
|
||||
### :bangbang: Chromeドライバーのインストールフラグ
|
||||
|
||||
<!---
|
||||
In Appium 1.x it was possible to customize the way Chromedriver was installed (as part of the UiAutomator2 driver for example), using the following command line flags:
|
||||
--->
|
||||
Appium 1.xでは、以下のコマンドラインフラグを使って、(例えばUiAutomator2ドライバーの一部として)Chromedriverをインストールする方法の変更が可能でした。
|
||||
|
||||
* `--chromedriver-skip-install`
|
||||
* `--chromedriver-version`
|
||||
* `--chromedriver-cdnurl`
|
||||
|
||||
<!---
|
||||
Because Appium 2.0 now installs drivers for you, and because these flags were implemented as NPM config flags, they will no longer work. Instead, use the following environment variables during driver installation:
|
||||
--->
|
||||
Appium 2.0では必要なドライバーだけインストールするようになり、またこれらのフラグはnpmの設定フラグとして実装されたため、これらのコマンドラインフラグは機能しません。代わりに、ドライバーのインストール時に以下の環境変数を使用してください:
|
||||
|
||||
* `APPIUM_SKIP_CHROMEDRIVER_INSTALL`
|
||||
* `CHROMEDRIVER_VERSION`
|
||||
* `CHROMEDRIVER_CDNURL`
|
||||
|
||||
For example:
|
||||
例:
|
||||
|
||||
```bash
|
||||
APPIUM_SKIP_CHROMEDRIVER_INSTALL=1 appium driver install uiautomator2
|
||||
```
|
||||
|
||||
### :bangbang: Driver-specific command line options
|
||||
### :bangbang: ドライバー特有のコマンドラインオプション
|
||||
|
||||
<!---
|
||||
With Appium 1.x, command-line options specific to particular drivers were all hosted on the main Appium server. So, for example, `--chromedriver-executable` was a CLI parameter you could use with Appium to set the location of a specific Chromedriver version for use with, say, the UiAutomator2 driver.
|
||||
--->
|
||||
Appium 1.xでは、特定のドライバに特化したコマンドラインオプションは、すべてAppiumサーバーに中継されていました。
|
||||
そのため、例えば`--chromedriver-executable`は、UiAutomator2ドライバーで使用する特定のChromedriverバージョンの場所を設定するためにAppiumで使用できるCLIパラメータでした。
|
||||
|
||||
<!--
|
||||
With Appium 2.x, all driver- and platform-specific CLI params have been moved to the drivers themselves. To access them, you'll now need to prepend the argument with the extension type (either `driver` or `plugin`) and the name of the extension. For example, `--chromedriver-executable` becomes `--driver-uiautomator2-chromedriver-executable`.
|
||||
-->
|
||||
Appium 2.xでは、すべてのドライバーとプラットフォーム固有の CLI パラメータは、それらのドライバー自体が管理するかたちに移行しました。これらにアクセスするには、引数の前に拡張機能の種類 (`driver` または `plugin`) と拡張機能の名前を付ける必要があります。例えば、`--chromedriver-executable` は `--driver-uiautomator2-chromedriver-executable` となります。
|
||||
|
||||
### :bangbang: Driver-specific automation commands
|
||||
### :bangbang: ドライバー特有の自動化コマンド
|
||||
|
||||
The definition of certain commands that pertain only to specific drivers has been moved to those
|
||||
<!---
|
||||
The definition of certain commands that pertain only to specific drivers has been moved to those
|
||||
drivers' implementations. For example, `pressKeyCode` is specific to the UiAutomator2 driver and is
|
||||
now understood only by that driver. In practice, the only breaking change here is the kind of error
|
||||
you would encounter if the appropriate driver is not installed. Previously, you would get a `501
|
||||
Not Yet Implemented` error if using a driver that didn't implement the command. Now, you will get
|
||||
a `404 Not Found` error because if a driver that doesn't know about the command is not active, the
|
||||
main Appium server will not define the route corresponding to the command.
|
||||
--->
|
||||
|
||||
特定のドライバーにのみ関係するコマンドの定義は、そのドライバーの実装に移行しました。
|
||||
例えば、`pressKeyCode`はUiAutomator2ドライバー特有のものなので、現在ではそのドライバーのみが解釈できます。
|
||||
実際には、適切なドライバーがインストールされていない場合に発生するエラーの種類が変わります。
|
||||
以前は、ドライバーが未実装のコマンドを実行すると `501 Not Yet Implemented` というエラーが返却されていました。
|
||||
現在では、コマンドを実装していないドライバーがアクティブでない場合、主Appiumサーバーはそのコマンドは定義されていないと処理し、`404 Not Found` エラーを返却します。
|
||||
|
||||
### :bangbang: Driver updates
|
||||
|
||||
<!--
|
||||
In the past, to get updates to your iOS or Android drivers, you'd simply wait for those updates to be rolled into a new release of Appium, and then update your Appium version. With Appium 2.x, the Appium server and the Appium drivers are versioned and released separately. This means that drivers can be on their own release cadence and that you can get driver updates as they happen, rather than waiting for a new Appium server release. The way to check for driver updates is with the CLI:
|
||||
-->
|
||||
|
||||
以前は、iOSやAndroidに関わるドライバーの更新を入手するために、Appiumの新しいリリースにそれらの更新が組み込まれるのを待ち、Appiumのバージョンを更新していました。
|
||||
Appium 2.xでは、AppiumサーバーとAppiumドライバーは各々にバージョンが管理され、別々にリリースされます。
|
||||
つまりドライバーは独自のリリース周期で、新しいAppiumサーバーのリリースを待つのではなく、その都度更新を適用することができます。
|
||||
|
||||
ドライバーの更新をCLIでチェックする方法:
|
||||
|
||||
```bash
|
||||
appium driver list --updates
|
||||
```
|
||||
|
||||
<!--
|
||||
If any updates are available, you can then run the `update` command for any given driver:
|
||||
-->
|
||||
|
||||
更新が入手可能であれば、任意のドライバーに対して `update` コマンドを実行することができます。
|
||||
|
||||
```bash
|
||||
appium driver update xcuitest
|
||||
```
|
||||
|
||||
<!--
|
||||
(For a complete description of the update command, check out the [Extension
|
||||
CLI](../cli/extensions.md) doc)
|
||||
-->
|
||||
|
||||
(更新コマンドの詳しい説明は [Extension CLI](https://appium.io/docs/en/latest/cli/extensions/#update) を確認してください。)
|
||||
|
||||
<!--
|
||||
To update the Appium server itself, you do the same thing as in the past: `npm i -g appium`. Now, installing new versions of the Appium server will leave your drivers intact, so the whole process will be much more quick.
|
||||
-->
|
||||
|
||||
Appium サーバー自体を更新するには、これまでと同じように `npm i -g appium` を実行します。現在、Appiumサーバーの新しいバージョンをインストールしても、ドライバーはそのままなので、プロセス全体がより迅速になります。
|
||||
|
||||
<!--
|
||||
If you would like to update to a specific version, not the latest, please uninstall the driver and install the desired version using the `install` subcommand instead of `update`.
|
||||
-->
|
||||
|
||||
最新のバージョンではなく、特定のバージョンに更新したい場合は、`update`の代わりに`install`サブコマンドを使ってドライバをアンインストールし、希望のバージョンをインストールしてください。
|
||||
|
||||
```bash
|
||||
appium driver uninstall xcuitest
|
||||
appium driver install xcuitest@4.11.1
|
||||
```
|
||||
|
||||
### :bangbang: Protocol changes
|
||||
### :bangbang: プロトコルの変更
|
||||
|
||||
<!--
|
||||
Appium's API is based on the [W3C WebDriver Protocol](https://www.w3.org/TR/webdriver/), and it has supported this protocol for years. Before the W3C WebDriver Protocol was designed as a web standard, several other protocols were used for both Selenium and Appium. These protocols were the "JSONWP" (JSON Wire Protocol) and "MJSONWP" (Mobile JSON Wire Protocol). The W3C Protocol differs from the (M)JSONWP protocols in a few small ways.
|
||||
-->
|
||||
|
||||
AppiumのAPIは[W3C WebDriver Protocol](https://www.w3.org/TR/webdriver/)に基づいており、何年もこのプロトコルをサポートしています。
|
||||
W3C WebDriver Protocolがウェブ標準として設計される以前は、SeleniumとAppiumの両方で他のプロトコルが使用されていました。それは、「JSONWP」(JSON Wire Protocol)と「MJSONWP」(Mobile JSON Wire Protocol)です。
|
||||
W3Cプロトコルと(M)JSONWPプロトコルはいくつか異なる点があります。
|
||||
|
||||
<!--
|
||||
Up until Appium 2.0, Appium supported both protocols, so that older Selenium/Appium clients could still communicate with newer Appium servers. Moving forward, support for older protocols will be removed.
|
||||
-->
|
||||
|
||||
### :bangbang: _Capabilities_
|
||||
Appium 2.0までは、古いSelenium/Appiumクライアントが新しいAppiumサーバーと通信できるように、Appiumは両方のプロトコルをサポートしていました。今後、古いプロトコルのサポートは削除されます。
|
||||
|
||||
### :bangbang: Capabilitiesはベンダープレフィックスを使用しなければならない
|
||||
|
||||
<!--
|
||||
One significant difference between old and new protocols is in the format of capabilities. Previously called "desired capabilities", and now called simply "capabilities", there is now a requirement for a so-called "vendor prefix" on any non-standard capabilities. The list of standard capabilities is given in the [WebDriver Protocol spec](https://www.w3.org/TR/webdriver/#capabilities), and includes a few commonly used capabilities such as `browserName` and `platformName`.
|
||||
-->
|
||||
|
||||
古いプロトコルと新しいプロトコルの大きな違いのひとつは、Capabilitiesのフォーマットにあります。以前は "desired capabilities" と呼ばれていましたが、現在は単に "capabilities" と呼ばれ、非標準の機能にはいわゆる "vendor prefix" が要求されるようになりました。標準として組み込まれているcapabilitiesは [WebDriver Protocol spec](https://www.w3.org/TR/webdriver/#capabilities) に記載されており、`browserName` や `platformName` などのよく使われるcapabilitiesが含まれています。
|
||||
|
||||
<!--
|
||||
These standard capabilities continue to be used as-is. All other capabilities must include a "vendor prefix" in their name. A vendor prefix is a string followed by a colon, such as `appium:`. Most of Appium's capabilities go beyond the standard W3C capabilities and must therefore include vendor prefixes (we recommend that you use `appium:` unless directed otherwise by documentation). For example:
|
||||
-->
|
||||
|
||||
これらの標準として組み込まれているcapabilitiesはそのまま使用され続けます。それ以外のすべてのcapabilitiesは、その名前に"vendor prefix"を 含まなければなりません。"vendor prefix"は、`appium:` のように、コロンが続く文字列です。Appiumのほとんどのcapabilitiesは、標準として組み込まれているcapabilitiesではないため、"vendor prefix"を含める必要があります(ドキュメントで指示がない限り、`appium:` を使用することを推奨します)。
|
||||
例えば、
|
||||
|
||||
- `appium:app`
|
||||
- `appium:noReset`
|
||||
- `appium:deviceName`
|
||||
|
||||
<!--
|
||||
This requirement may or may not be a breaking change for your test suites when targeting Appium 2.0. If you're using an updated Appium client (at least one maintained by the Appium team), the client will add the `appium:` prefix for you on all necessary capabilities automatically. New versions of [Appium Inspector](https://github.com/appium/appium-inspector) will also do this. Cloud-based Appium providers may also do this. So simply be aware that if you get any messages to the effect that your capabilities lack a vendor prefix, this is how you solve that problem.
|
||||
-->
|
||||
|
||||
この要件は、Appium 2.0をターゲットにしているテストスイートにとって破壊的な変更になるかもしれませんし、ならないかもしれません。
|
||||
アップデートされたAppiumクライアント(少なくとも Appium チームによってメンテナンスされているもの)を使用している場合、クライアントは自動的にすべての必要なcapabilitiesに `appium:` 接頭辞を追加します。新しいバージョンの[Appium Inspector](https://github.com/appium/appium-inspector)も同様です。クラウドベースのAppiumプロバイダもこれを行うかもしれません。
|
||||
そのため、もしあなたが使っていcapabilitiesに vendor prefix がない旨のメッセージが表示された場合は、この方法で問題を解決することができます。
|
||||
|
||||
<!--
|
||||
On a related note, it will no longer be possible to start Appium sessions using WebDriver clients that don't support the W3C protocol (see below for a comment to this effect for the WD library).
|
||||
-->
|
||||
|
||||
To make everyone's lives a bit easier, we've also introduced the option of wrapping up all Appium-related capabilities into one object capability, `appium:options`. You can bundle together anything that you would normally put an `appium:` prefix on into this one capability. Here's an example (in raw JSON) of how you might start an iOS session on the Safari browser using `appium:options`:
|
||||
これに関連して、W3CプロトコルをサポートしていないWebDriverクライアントを使用してAppiumセッションを開始することはできなくなります(WDライブラリに関するこの趣旨のコメントは以下を参照してください)。
|
||||
|
||||
<!-- To make everyone's lives a bit easier, we've also introduced the option of wrapping up all Appium-related capabilities into one object capability, `appium:options`. You can bundle together anything that you would normally put an `appium:` prefix on into this one capability. Here's an example (in raw JSON) of how you might start an iOS session on the Safari browser using `appium:options`: -->
|
||||
|
||||
みなさんの活動を少し楽にするために、Appiumに関連する全てのcapabilitiesを一つのオブジェクトにまとめるオプション(`appium:options`)も導入しました。通常、`appium:`接頭辞を付けるものを、この1つのcapabilityにまとめることができます。以下は `appium:options` を使ってSafariブラウザ上でiOSセッションを開始する例(JSON)です:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -209,106 +302,187 @@ To make everyone's lives a bit easier, we've also introduced the option of wrapp
|
||||
}
|
||||
```
|
||||
|
||||
(Of course, each client will have a different way of creating structured capabilities like `appium:options` or other ones that you might have seen such as `goog:chromeOptions`). NB: capabilities that show up in `appium:options` will overwrite capabilities of the same name that show up at the top level of the object. (The new `appium:options` syntax support by cloud providers may vary.)
|
||||
<!-- (Of course, each client will have a different way of creating structured capabilities like `appium:options` or other ones that you might have seen such as `goog:chromeOptions`).
|
||||
|
||||
For more information on capabilities, have a look at the [Capabilities Guide](caps.md).
|
||||
!!! note
|
||||
|
||||
### :bangbang: _Removed Commands_
|
||||
Capabilities included in the `appium:options` object will overwrite capabilities of the same
|
||||
name that are used outside of this object. (The `appium:options` syntax support by cloud
|
||||
providers may vary.)-->
|
||||
|
||||
In addition to commands which have been moved to driver implementations, commands which were a part of the old JSON Wire Protocol and not a part of the W3C Protocol are no longer available:
|
||||
(もちろん、`appium:options`のような構造化されたcapabilityや、`goog:chromeOptions`のような構造化されたcapabilityは、クライアントによって作成方法が異なります。)
|
||||
|
||||
- TODO (these commands are being identified and removed and will be updated here when complete)
|
||||
!!! note
|
||||
|
||||
If you use a modern Appium or Selenium client, you should no longer have access to these anyway, so any breaking changes should appear on the client side first and foremost.
|
||||
`appium:options`で表示されるcapabilityは、オブジェクトのトップレベルで表示される同名のcapabilityを上書きします。
|
||||
(新しい `appium:options` 構文のサポートは、クラウドプロバイダによって異なる場合があります。)
|
||||
|
||||
### :bangbang: Image analysis features moved to plugin
|
||||
<!-- For more information on capabilities, have a look at the [Capabilities Guide](caps.md). -->
|
||||
|
||||
One of the design goals for Appium 2.0 is to migrate non-core features into special extensions called [plugins](../ecosystem/plugins.md). This allows people to opt into features which require extra time to download or extra system setup. The various image-related features of Appium (image comparison, finding elements by image, etc...) have been moved into an officially supported plugin called [images](https://github.com/appium/appium/tree/master/packages/images-plugin).
|
||||
ケイパビリティの詳細については、[Capabilities Guide](https://appium.io/docs/en/latest/guides/caps/)をご覧ください。
|
||||
|
||||
If you use these image-related methods, to continue accessing them you will need to do two things.
|
||||
### :bangbang: 削除されたコマンド
|
||||
|
||||
1. Install the plugin: `appium plugin install images`
|
||||
2. Ensure you start the Appium server with access to run the plugin by including it in the list of plugins designated on the command line, e.g., `appium --use-plugins=images`
|
||||
<!-- In addition to commands which have been moved to driver implementations, commands which were a part of the old JSON Wire Protocol and not a part of the W3C Protocol are no longer available: -->
|
||||
|
||||
Image-related commands will also be removed on the client side of things, which means you will need to follow the instructions on the plugin README for installing client-side plugins to access these features.
|
||||
ドライバの実装に移行したコマンドに加え、旧JSON Wireプロトコルの一部であり、W3Cプロトコルの一部ではないコマンドは使用できなくなりました:
|
||||
|
||||
### :bangbang: Execute Driver Script command moved to plugin
|
||||
<!-- - TODO (these commands are being identified and removed and will be updated here when complete) -->
|
||||
|
||||
If you use the advanced Execute Driver Script feature (which allows you to send in a WebdriverIO script to have it executed completely on the server instead of command-by-command from the client), this functionality has been moved to a plugin. Here's what to do to keep using it:
|
||||
- TODO(これらのコマンドは特定・削除中であり、完了次第ここに更新されます)
|
||||
|
||||
1. Install the plugin: `appium plugin install execute-driver`
|
||||
2. Ensure you start the Appium server with access to run the plugin by including it in the list of plugins designated on the command line, e.g., `appium --use-plugins=execute-driver`
|
||||
<!-- If you use a modern Appium or Selenium client, you should no longer have access to these anyway, so any breaking changes should appear on the client side first and foremost. -->
|
||||
|
||||
### :bangbang: External Files No Longer Supported for `--nodeconfig`, `--default-capabilities`, `--allow-insecure` and `--deny-insecure`
|
||||
最新のAppiumやSeleniumクライアントを使用している場合、これらにアクセスすることはできないため、どのような破壊的変更もまずはクライアント側に現れるはずです。
|
||||
|
||||
These options can be provided as strings on the command line (a JSON string for `--nodeconfig` and a comma-separated list of strings for `--allow-insecure` and `--deny-insecure`). Arguments provided on the command line will likely need to be quoted or escaped.
|
||||
### :bangbang: 画像解析機能をプラグインに移行
|
||||
|
||||
The recommended method to provide these options is now via a [configuration file](#tada-configuration-files).
|
||||
<!-- One of the design goals for Appium 2.0 is to migrate non-core features into special extensions called [plugins](../ecosystem/plugins.md). This allows people to opt into features which require extra time to download or extra system setup. The various image-related features of Appium (image comparison, finding elements by image, etc...) have been moved into an officially supported plugin called [images](https://github.com/appium/appium/tree/master/packages/images-plugin). -->
|
||||
|
||||
In summary, if you are using a JSON Appium config file, you can simply cut-and-paste the contents of your "nodeconfig" JSON file into the value of the `server.nodeconfig` property. Any CSV-like files you had previously provided for `--allow-insecure` and `--deny-insecure` become the values of the `server.allow-insecure` and `server.deny-insecure` properties in the Appium config files (respectively); both are arrays of strings.
|
||||
Appium 2.0の設計目標の1つは、非コア機能を[plugins](https://appium.io/docs/en/latest/ecosystem/plugins/)と呼ばれる特別な拡張機能に移行することです。これにより、ダウンロード時間やシステム設定が追加で必要となる機能を選択して利用できるようになります。Appiumの様々な画像関連機能(画像比較、画像による要素の検索など)は、[images](https://github.com/appium/appium/tree/master/packages/images-plugin)という公式にサポートされているプラグインに移動されました。
|
||||
|
||||
### :bangbang: Old drivers removed
|
||||
<!-- If you use these image-related methods, to continue accessing them you will need to do two things. -->
|
||||
|
||||
The old iOS and Android (UiAutomator 1) drivers and related tools (e.g., `authorize-ios`) have been removed. They haven't been relevant for many years anyway.
|
||||
これらの画像関連メソッドを使用する場合、以下の2つのことを行う必要があります。
|
||||
|
||||
<!-- 1. Install the plugin: `appium plugin install images` -->
|
||||
<!-- 2. Ensure you start the Appium server with access to run the plugin by including it in the list of plugins designated on the command line, e.g., `appium --use-plugins=images` -->
|
||||
|
||||
### :bangbang: Server can no longer be started with `--port 0`
|
||||
1. プラグインをインストールする: `appium plugin install images`.
|
||||
2. コマンドラインで指定したプラグインリストにプラグインを含めることで、プラグインを実行できる状態でAppiumサーバーを起動する。例:`appium --use-plugins=images`
|
||||
|
||||
In Appium 1.x, it was possible to specify `--port 0` during server startup. This had the effect of
|
||||
<!-- Image-related commands will also be removed on the client side of things, which means you will need to follow the instructions on the plugin README for installing client-side plugins to access these features. -->
|
||||
|
||||
画像関連のコマンドはクライアント側でも削除されるため、これらの機能にアクセスするには、プラグインのREADMEにあるクライアント側プラグインのインストールの指示に従う必要があります。
|
||||
|
||||
### :bangbang: Execute Driver Scriptコマンドがプラグインに移動
|
||||
|
||||
<!-- If you use the advanced Execute Driver Script feature (which allows you to send in a WebdriverIO script to have it executed completely on the server instead of command-by-command from the client), this functionality has been moved to a plugin. Here's what to do to keep using it: -->
|
||||
|
||||
高度なExecute Driver Script機能(WebdriverIOスクリプトを送信して、クライアントからコマンドごとに実行するのではなく、サーバー上で完全に実行させる機能)はプラグインに移動しました。この機能を使い続けるには以下の方法を使用してください:
|
||||
|
||||
<!-- 1. Install the plugin: `appium plugin install execute-driver`
|
||||
2. Ensure you start the Appium server with access to run the plugin by including it in the list of plugins designated on the command line, e.g., `appium --use-plugins=execute-driver` -->
|
||||
|
||||
1. プラグインをインストールする: `appium plugin install execute-driver`.
|
||||
2. コマンドラインで指定したプラグインリストにプラグインを含めることで、プラグインを実行できる状態でAppiumサーバーを起動する。例:`appium --use-plugins=execute-driver`
|
||||
|
||||
### :bangbang: `--nodeconfig` `--default-capabilities ` `--allow-insecure` `--deny-insecure`での外部ファイルのサポート終了
|
||||
|
||||
<!-- These options can be provided as strings on the command line (a JSON string for `--nodeconfig` and a comma-separated list of strings for `--allow-insecure` and `--deny-insecure`). Arguments provided on the command line will likely need to be quoted or escaped. -->
|
||||
|
||||
これらのオプションはコマンドラインで文字列として指定できます(`--nodeconfig`の場合はJSON文字列、`--allow-insecure`と`--deny-insecure`の場合はカンマ区切りの文字列リスト)。コマンドラインで指定する引数は、引用符で囲むかエスケープする必要があります。
|
||||
|
||||
<!-- The recommended method to provide these options is now via a [configuration file](#tada-configuration-files). -->
|
||||
|
||||
これらのオプションを提供するために推奨される方法は、[Configuration File](#configuration-files)を使うことです。
|
||||
|
||||
<!-- In summary, if you are using a JSON Appium config file, you can simply cut-and-paste the contents of your "nodeconfig" JSON file into the value of the `server.nodeconfig` property. Any CSV-like files you had previously provided for `--allow-insecure` and `--deny-insecure` become the values of the `server.allow-insecure` and `server.deny-insecure` properties in the Appium config files (respectively); both are arrays of strings. -->
|
||||
|
||||
つまり、JSON Appium configファイルを使用している場合、単純に "nodeconfig" JSON ファイルの内容を `server.nodeconfig` プロパティの値にカット&ペーストすることができます。 以前 `--allow-insecure` と `--deny-insecure` のために提供した CSV のようなファイルは、Appium config ファイルの `server.allow-insecure` プロパティと `server.deny-insecure` プロパティの値になります(それぞれ文字列の配列)。
|
||||
|
||||
### :bangbang: 古いドライバーを削除
|
||||
|
||||
<!-- The old iOS and Android (UiAutomator 1) drivers and related tools (e.g., `authorize-ios`) have been removed. They haven't been relevant for many years anyway. -->
|
||||
|
||||
古いiOSとAndroid(UiAutomator 1)のドライバーと関連ツール(例えば`authorize-ios`)は削除されました。いずれにせよ、これらは何年も関連していません。
|
||||
|
||||
### :bangbang: サーバは `--port 0` で起動することはできない
|
||||
|
||||
<!-- In Appium 1.x, it was possible to specify `--port 0` during server startup. This had the effect of
|
||||
starting Appium on a random free port. In Appium 2.0, port values must be `1` or higher. The random
|
||||
port assignment was never an intentional feature of Appium 1.x, but a consequence of how Node's
|
||||
HTTP servers work and the fact that there was no port input validation in Appium 1.x. If you want
|
||||
to find a random free port to start Appium on, you must now take care of this on your own prior to
|
||||
starting Appium. Starting Appium on an explicit and known port is the correct practice moving
|
||||
forward.
|
||||
forward. -->
|
||||
|
||||
### :warning: Internal packages renamed
|
||||
Appium 1.xでは、サーバー起動時に`--port 0`を指定することができました。
|
||||
これはランダムな空きポートで Appium を起動するという効果があります。Appium 2.0 では、ポートの値は `1` 以上でなければなりません。
|
||||
ランダムなポートのランダムな割り当ては、Appium 1.x の意図的な機能ではありませんでした。HTTP サーバーがどのように動作するか、そして Appium 1.xにはポート入力の検証がなかった結果です。
|
||||
Appium を起動するためにランダムな空きポートを見つけたい場合は、Appium を起動する前に自分でこの処理を行う必要があります。
|
||||
明示的な既知のポートでAppiumを起動するのが、今後の正しいやり方です。
|
||||
|
||||
Some Appium-internal NPM packages have been renamed (for example, `appium-base-driver` is now `@appium/base-driver`). This is not a breaking change for Appium users, only for people who have built software that directly incorporates Appium's code.
|
||||
### :warning: 内部パッケージの名称変更
|
||||
|
||||
### :warning: "WD" JavaScript client library no longer supported
|
||||
<!-- Some Appium-internal NPM packages have been renamed (for example, `appium-base-driver` is now `@appium/base-driver`). This is not a breaking change for Appium users, only for people who have built software that directly incorporates Appium's code. -->
|
||||
|
||||
For many years, some of Appium's authors maintained the [WD](https://github.com/admc/wd) client library. This library has been deprecated and has not been updated for use with the W3C WebDriver protocol. As such, if you're using this library you'll need to move to a more modern one. We recommend [WebdriverIO](https://webdriver.io).
|
||||
一部の Appium 内部のnpmパッケージの名前が変更されました(例えば、`appium-base-driver` は `@appium/base-driver` になりました)。これはAppiumのユーザーにとって大きな変更ではなく、Appiumのコードを直接組み込んだソフトウェアをビルドしている人にとっての変更です。
|
||||
|
||||
### :warning: Appium Inspector split out from Appium Desktop
|
||||
### :warning: "WD "JavaScriptクライアント・ライブラリがサポート終了
|
||||
|
||||
The inspecting portion of Appium Desktop has been moved to its own app, Appium Inspector: [github.com/appium/appium-inspector](https://github.com/appium/appium-inspector). It's fully compatible with Appium 2.0 servers. Simply download it and run it on its own. You no longer need the GUI Appium Desktop server to inspect apps. The Appium Desktop server will continue to be supported at its original site: [github.com/appium/appium-desktop](https://github.com/appium/appium-desktop). It will simply no longer bundle the Inspector with it. Note that Appium Desktop 1.21 and lower versions depend on the deprecated [WD](https://github.com/admc/wd) client, and are not compatible with Appium 2.0. There is currently no Appium 2.0 support for Appium Desktop planned, now that the Inspector is a standalone app.
|
||||
<!-- For many years, some of Appium's authors maintained the [WD](https://github.com/admc/wd) client library. This library has been deprecated and has not been updated for use with the W3C WebDriver protocol. As such, if you're using this library you'll need to move to a more modern one. We recommend [WebdriverIO](https://webdriver.io). -->
|
||||
|
||||
You can also now use the Appium Inspector without downloading anything, by visiting the [web version of Appium Inspector](https://inspector.appiumpro.com). Note that to test against local servers, you'll need to start the server with `--allow-cors` so that the browser-based version of Appium Inspector can access your Appium server to start sessions.
|
||||
何年もの間、Appiumの作者の一部は[WD](https://github.com/admc/wd)クライアントライブラリを保守していました。このライブラリは非推奨であり、W3C WebDriverプロトコルで使用するためには更新されていません。そのため、このライブラリを使用している場合は、より最新のものに移行する必要があります。[WebdriverIO](https://webdriver.io)をお勧めします。
|
||||
|
||||
## Major New Features
|
||||
### :warning: Appium InspectorがAppium Desktopから分離
|
||||
|
||||
Apart from the breaking changes mentioned above, in this section is a list of some of the major new features you may wish to take advantage of with Appium 2.0.
|
||||
<!-- The inspecting portion of Appium Desktop has been moved to its own app, Appium Inspector: [github.com/appium/appium-inspector](https://github.com/appium/appium-inspector). It's fully compatible with Appium 2.0 servers. Simply download it and run it on its own. You no longer need the GUI Appium Desktop server to inspect apps. The Appium Desktop server will continue to be supported at its original site: [github.com/appium/appium-desktop](https://github.com/appium/appium-desktop). It will simply no longer bundle the Inspector with it. Note that Appium Desktop 1.21 and lower versions depend on the deprecated [WD](https://github.com/admc/wd) client, and are not compatible with Appium 2.0. There is currently no Appium 2.0 support for Appium Desktop planned, now that the Inspector is a standalone app. -->
|
||||
|
||||
### Plugins
|
||||
Appium Desktopのインスペクション部分は、専用のアプリAppium Inspector [github.com/appium/appium-inspector](https://github.com/appium/appium-inspector) に移動しました。Appium 2.0サーバーと完全に互換性があります。ダウンロードして実行するだけです。アプリを検査するためにGUIのAppium Desktopサーバーはもう必要ありません。Appium Desktopサーバーは、[github.com/appium/appium-desktop](https://github.com/appium/appium-desktop)で引き続きサポートされます。単にInspectorがバンドルされなくなるだけです。Appium Desktop 1.21以下のバージョンは、非推奨の[WD](https://github.com/admc/wd)クライアントに依存しており、Appium 2.0と互換性がないことに注意してください。現在、Appium DesktopのAppium 2.0サポートは予定されていません。
|
||||
|
||||
<!-- You can also now use the Appium Inspector without downloading anything, by visiting the [web version of Appium Inspector](https://inspector.appiumpro.com). Note that to test against local servers, you'll need to start the server with `--allow-cors` so that the browser-based version of Appium Inspector can access your Appium server to start sessions. -->
|
||||
|
||||
また、[Web 版 Appium Inspector](https://inspector.appiumpro.com) にアクセスすることで、何もダウンロードせずに Appium Inspector を使用できるようになりました。なお、ローカルサーバーに対してテストを行う場合は、ブラウザベースのAppium InspectorがAppiumサーバーにアクセスしてセッションを開始できるように、サーバーを `--allow-cors` で起動する必要があります。
|
||||
|
||||
## 主な新機能
|
||||
|
||||
<!-- Apart from the breaking changes mentioned above, in this section is a list of some of the major new features you may wish to take advantage of with Appium 2.0. -->
|
||||
|
||||
上記の変更点とは別に、このセクションではAppium 2.0の主な新機能を紹介します。
|
||||
|
||||
### プラグイン
|
||||
|
||||
#### :tada: _Server Plugins_
|
||||
|
||||
Appium extension authors can now develop their own server plugins, which can intercept and modify
|
||||
<!-- Appium extension authors can now develop their own server plugins, which can intercept and modify
|
||||
any Appium command, or even adjust the way the underlying Appium HTTP server itself works. To learn
|
||||
more about plugins, read the new [Appium Introduction](../intro/index.md). Interested in building
|
||||
a plugin? Check out the [Building Plugins](../ecosystem/build-plugins.md) guide.
|
||||
a plugin? Check out the [Building Plugins](../ecosystem/build-plugins.md) guide. -->
|
||||
|
||||
#### :tada: _Client Plugins_
|
||||
Appium extensionの作者は、独自のサーバー・プラグインを開発できるようになりました。
|
||||
Appium HTTPサーバー自体の動作方法を調整することもできます。
|
||||
プラグインの詳細については、新しい[Appium Introduction](../intro/index.md)をお読みください。
|
||||
プラグインを作ることに興味がありますか? [プラグインの構築](https://appium.io/docs/en/latest/developing/build-plugins/) ガイドをチェックしてください。
|
||||
|
||||
TODO
|
||||
### :tada: どこからでもドライバーとプラグインをインストール
|
||||
|
||||
### :tada: Install drivers and plugins from anywhere
|
||||
|
||||
You're no longer limited to the drivers that come with Appium, or that the Appium team even knows
|
||||
<!-- You're no longer limited to the drivers that come with Appium, or that the Appium team even knows
|
||||
about! Appium extension authors can now develop custom drivers, which can be downloaded or
|
||||
installed via Appium's [Extension CLI](../cli/extensions.md) from NPM, Git, GitHub, or even the
|
||||
installed via Appium's [Extension CLI](../cli/extensions.md) from `npm`, `git`, GitHub, or even the
|
||||
local filesystem. Interested in building a driver? Check out the [Building
|
||||
Drivers](../ecosystem/build-drivers.md) guide.
|
||||
Drivers](../developing/build-drivers.md) guide. -->
|
||||
|
||||
もはやAppium付属のドライバーや、Appiumチームが知っているドライバーに限定されることはありません!Appiumエクステンションの作者は、カスタムドライバを開発できるようになりました。
|
||||
Appiumの[Extension CLI](https://appium.io/docs/en/latest/cli/extensions/)経由で、`npm`、`git`、GitHub、またはローカルのファイルシステムからダウンロードまたはインストールできます。
|
||||
ドライバのビルドに興味がありますか? [ドライバのビルド](https://appium.io/docs/en/latest/developing/build-drivers/) ガイドを参照してください。
|
||||
|
||||
### :tada: Configuration Files
|
||||
|
||||
Appium now supports _configuration files_ in addition to command-line arguments. In a nutshell, nearly all arguments which Appium 1.x required to be provided on the CLI are now able to be expressed via a configuration file. Configuration files may be in JSON, JS, or YAML format. See the [Config Guide](config.md) for a full explanation.
|
||||
<!-- Appium now supports _configuration files_ in addition to command-line arguments. In a nutshell,
|
||||
nearly all arguments which Appium 1 required to be provided on the CLI are now able to be expressed
|
||||
via a configuration file. Configuration files may be in JSON, JS, or YAML format. See the
|
||||
[Config Guide](./config.md) for a full explanation. -->
|
||||
|
||||
## Special Notes for Cloud Providers
|
||||
Appiumは、コマンドライン引数に加え、_設定ファイル_ もサポートするようになりました。つまりAppium 1がCLIで提供することを要求していたほぼすべての引数が、設定ファイルを介して表現できるようになりました。設定ファイルは JSON, JS, YAML 形式があります。設定ファイルは [Config Guide](https://appium.io/docs/en/latest/guides/config/) を参照してください。
|
||||
|
||||
The rest of this document has applied to Appium generally, but some of the architectural changes in Appium 2.0 will constitute breaking changes for Appium-related service providers, whether a cloud-based Appium host or an internal service. At the end of the day, the maintainer of the Appium server is responsible for installing and making available the various Appium drivers and plugins that end users may wish to use.
|
||||
## クラウド・プロバイダーに関する特記事項
|
||||
|
||||
We encourage cloud providers to thoroughly read and understand our [recommendation for cloud
|
||||
provider capabilities](caps.md#special-notes-for-cloud-providers) in order to support user needs in
|
||||
an industry-compatible way!
|
||||
<!-- The rest of this document has applied to Appium generally, but some of the architectural changes in
|
||||
Appium 2 will constitute breaking changes for Appium-related service providers, whether a
|
||||
cloud-based Appium host or an internal service. At the end of the day, the maintainer of the Appium
|
||||
server is responsible for installing and making available the various Appium drivers and plugins
|
||||
that end users may wish to use. -->
|
||||
|
||||
このドキュメントの残りの部分はAppium全般に適用されていますが、Appium 2のアーキテクチャ上の変更の一部はクラウドベースのAppiumホストであれ、内部サービスであれ、Appium関連のサービスプロバイダーにとって破壊的な変更となります。結局のところ、Appiumサーバーを保守する人は、エンドユーザーが使用したいと思うであろう様々なAppiumドライバーやプラグインをインストールし、利用できるようにする責任を持ちます。
|
||||
|
||||
<!-- We encourage cloud providers to thoroughly read and understand our [recommendation for cloud
|
||||
provider capabilities](./caps.md#special-notes-for-cloud-providers) in order to support user needs in
|
||||
an industry-compatible way! -->
|
||||
|
||||
クラウドプロバイダーには、業界と互換性のある方法でユーザーのニーズをサポートするために、私たちの[クラウドプロバイダーの能力に関する推奨事項](https://appium.io/docs/en/latest/guides/caps/#special-notes-for-cloud-providers) を十分に読み、理解することをお勧めします!
|
||||
|
||||
<!--
|
||||
for japanese translator
|
||||
Links to documents not translated into Japanese refer to the English version.
|
||||
-->
|
||||
|
||||
@@ -72,7 +72,7 @@ nav:
|
||||
- developing/build-plugins.md
|
||||
- developing/build-docs.md
|
||||
- developing/build-doctor-checks.md
|
||||
- Contributing:
|
||||
- contributing/index.md
|
||||
- contributing/develop.md
|
||||
- contributing/config-system.md
|
||||
- Developer Reference:
|
||||
- developing/config-system.md
|
||||
- Contributing: contributing.md
|
||||
- Sponsors: sponsors.md
|
||||
|
||||
@@ -34,13 +34,13 @@ nav:
|
||||
- ecosystem/clients.md
|
||||
- ecosystem/plugins.md
|
||||
- ecosystem/tools.md
|
||||
- CLI Reference:
|
||||
- 命令行参考:
|
||||
- cli/index.md
|
||||
- cli/args.md
|
||||
- cli/env-vars.md
|
||||
- cli/extensions.md
|
||||
- cli/setup.md
|
||||
- Command Reference:
|
||||
- 命令参考:
|
||||
- commands/index.md
|
||||
- commands/base-driver.md
|
||||
- commands/execute-driver-plugin.md
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -1,10 +1,6 @@
|
||||
<div class="appium-sponsor-thanks">
|
||||
Supported by
|
||||
|
||||
<a href="https://www.headspin.io/solutions/appium-mobile-test-automation">
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-headspin.png" />
|
||||
</a>
|
||||
|
||||
<a href="https://www.browserstack.com/browserstack-appium?utm_campaigncode=701OW00000AoUTQYA3&utm_medium=partnered&utm_source=appium">
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-browserstack-dark.png" />
|
||||
</a>
|
||||
|
||||
@@ -2,68 +2,62 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Server Command-Line Arguments
|
||||
title: 服务器命令行参数
|
||||
---
|
||||
|
||||
To start the Appium server, you may either run `appium` or `appium server`. The `server` subcommand
|
||||
is considered to be the default, so if you omit it, Appium will interpret this as your request to
|
||||
run the Appium server.
|
||||
要启动Appium服务器,您可以运行`appium`或`appium server`。`server`子命令是他的默认命令,因此如果省略它,Appium会将认为您想要运行Appium服务器。
|
||||
|
||||
The invocation of `appium` (or `appium server`) can take a number of arguments, which are detailed
|
||||
below.
|
||||
`appium`(或`appium server`)的调用可以接受多个参数,详细信息如下。
|
||||
|
||||
!!! note
|
||||
!!! 注意
|
||||
|
||||
All of these arguments can be set via a [Configuration File](../guides/config.md) instead if
|
||||
you want. Any arguments set on the command line will override any arguments found in
|
||||
a configuration file.
|
||||
|
||||
|
||||
|<div style="width:12em">Argument</div>|Description|Type|<div style="width:8em">Default</div>|Aliases|
|
||||
如果您愿意,所有这些参数都可以通过[配置文件](../guides/config.md)设置。命令行上设置的任何参数都将覆盖配置文件中的参数。
|
||||
|
||||
|<div style="width:12em">参数</div>|描述|类型|<div style="width:8em">默认值</div>|别名|
|
||||
|--|--|--|--|--|
|
||||
|`--address`|IP address to listen on|string|`0.0.0.0`|`-a`|
|
||||
|`--allow-cors`|Whether the Appium server should allow web browser connections from any host|boolean|`false`||
|
||||
|`--allow-insecure`|Set which insecure features are allowed to run in this server's sessions. Features are defined on a driver level; see documentation for more details. Note that features defined via `--deny-insecure` will be disabled, even if also listed here. If string, a path to a text file containing policy or a comma-delimited list.|array<string>|`[]`||
|
||||
|`--base-path`|Base path to use as the prefix for all webdriver routes running on the server|string|`""`|`-pa`|
|
||||
|`--callback-address`|Callback IP address (default: same as `--address`)|string||`-ca`|
|
||||
|`--callback-port`|Callback port (default: same as `--port`) (Value must be between `1` and `65535`)|integer|`4723`|`-cp`|
|
||||
|`--config`|Path to an [Appium configuration JSON file](../guides/config.md)|string|||
|
||||
|`--debug-log-spacing`|Add exaggerated spacing in logs to help with visual inspection|boolean|`false`||
|
||||
|`--default-capabilities`|Set the default desired capabilities, which will be set on each session unless overridden by received capabilities. If a string, a path to a JSON file containing the capabilities, or raw JSON.|object||`-dc`|
|
||||
|`--deny-insecure`|Set which insecure features are not allowed to run in this server's sessions. Features are defined on a driver level; see documentation for more details. Features listed here will not be enabled even if also listed in `--allow-insecure`, and even if `--relaxed-security` is enabled. If string, a path to a text file containing policy or a comma-delimited list.|array<string>|`[]`||
|
||||
|`--driver`|Driver-specific configuration. Keys should correspond to driver package names|object|||
|
||||
|`--drivers-import-chunk-size`|The maximum amount of drivers that could be imported in parallel on server startup|number|`3`||
|
||||
|`--keep-alive-timeout`|Number of seconds the Appium server should apply as both the keep-alive timeout and the connection timeout for all requests. Setting this to `0` disables the timeout.|integer|`600`|`-ka`|
|
||||
|`--local-timezone`|Use local timezone for timestamps|boolean|`false`||
|
||||
|`--log`|Also send log output to this file|string||`-g`|
|
||||
|`--log-filters`|One or more log filtering rules|array|||
|
||||
|`--log-level`|Log level (console[:file]) (Value must be one of: `info`, `info:debug`, `info:info`, `info:warn`, `info:error`, `warn`, `warn:debug`, `warn:info`, `warn:warn`, `warn:error`, `error`, `error:debug`, `error:info`, `error:warn`, `error:error`, `debug`, `debug:debug`, `debug:info`, `debug:warn`, `debug:error`)|string|`debug`||
|
||||
|`--log-format`|Log format (Value must be to one of: `text`, `json`, `pretty_json`). If logs are printed as JSON then the text coloring is always disabled.|string|`text`||
|
||||
|`--log-no-colors`|Do not use color in console output|boolean|`false`||
|
||||
|`--log-timestamp`|Show timestamps in console output|boolean|`false`||
|
||||
|`--long-stacktrace`|Add long stack traces to log entries. Recommended for debugging only.|boolean|`false`||
|
||||
|`--no-perms-check`|Skip various permission checks on the server startup|boolean|`false`||
|
||||
|`--nodeconfig`|Path to configuration JSON file to register Appium as a node with Selenium Grid 3; otherwise the configuration itself|string|||
|
||||
|`--plugin`|Plugin-specific configuration. Keys should correspond to plugin package names|object|||
|
||||
|`--plugins-import-chunk-size`|The maximum amount of plugins that could be imported in parallel on server startup|number|`7`||
|
||||
|`--port`|Port to listen on (Value must be between `1` and `65535`)|integer|`4723`|`-p`|
|
||||
|`--relaxed-security`|Disable additional security checks, so it is possible to use some advanced features, provided by drivers supporting this option. Only enable it if all the clients are in the trusted network and it's not the case if a client could potentially break out of the session sandbox. Specific features can be overridden by using `--deny-insecure`|boolean|`false`||
|
||||
|`--session-override`|Enables session override (clobbering)|boolean|`false`||
|
||||
|`--ssl-cert-path`|Absolute path to the `.cert` file if TLS is used. Must be provided together with `--ssl-key-path`. See the [SSL/TLS/SPDY Support guide](../guides/tls.md) for details|string|||
|
||||
|`--ssl-key-path`|Absolute path to the `.key` file if TLS is used. Must be provided together with `--ssl-cert-path`. See the [SSL/TLS/SPDY Support guide](../guides/tls.md) for details|string|||
|
||||
|`--strict-caps`|Cause sessions to fail if desired caps are sent in that Appium does not recognize as valid for the selected device|boolean|`false`||
|
||||
|`--tmp`|Absolute path to directory Appium can use to manage temp files|string|Windows: `C:\Windows\Temp`<br>Others: `/tmp`||
|
||||
|`--trace-dir`|Absolute path to directory Appium can use to save iOS instrument traces|string|`<tmp>/appium-instruments`||
|
||||
|`--use-drivers`|A list of drivers to activate. By default, all installed drivers will be activated.|array<string>|`[]`||
|
||||
|`--use-plugins`|A list of plugins to activate. To activate all plugins, the value should be an array with a single item `"all"`.|array<string>|`[]`||
|
||||
|`--webhook`|Also send log output to this http listener|string||`-G`|
|
||||
|`--address`|要监听的IP地址|string|`0.0.0.0`|`-a`|
|
||||
|`--allow-cors`|Appium服务器是否允许来自任何主机的web浏览器连接|boolean|`false`||
|
||||
|`--allow-insecure`|设置允许在此服务器的会话中运行哪些不安全功能。功能是在驱动程序层定义的;有关更多详细信息,请参阅文档。请注意,通过`--deny-insecure`指定的功能即使在这里列出也将被禁用。如果值是字符串,则表示是包含策略或逗号分隔列表的文本文件的路径。|array<string>|`[]`||
|
||||
|`--base-path`|用作服务器上运行的所有WebDriver路由的前置路径|string|`""`|`-pa`|
|
||||
|`--callback-address`|回调IP地址(默认值:与`--address`相同)|string||`-ca`|
|
||||
|`--callback-port`|回调端口(默认值:与`--port`相同)(值必须介于`1`和`65535`)|integer|`4723`|`-cp`|
|
||||
|`--config`|[Appium JSON格式配置文件](../guides/config.md)的路径|string|||
|
||||
|`--debug-log-spacing`|在日志中添加夸张的间距以便于进行查看。|boolean|`false`||
|
||||
|`--default-capabilities`|设置默认的所需功能,将在每个会话上设置这些功能,除非被新的配置覆盖。如果值是字符串,则表示包含功能的JSON文件的路径,或原始JSON字符串。|object||`-dc`|
|
||||
|`--deny-insecure`|设置禁止在此服务器的会话中运行的哪些不安全功能。功能是在驱动程序层定义的;有关更多详细信息,请参阅文档。即使在`--allow-insecure`中列出,并且启用了`--relaxed-securities`,此处列出的功能也会被禁用。如果值是字符串,则表示是包含策略或逗号分隔列表的文本文件的路径。|array<string>|`[]`||
|
||||
|`--driver`|驱动程序特定配置。键名应与驱动程序包名称相对应|object|||
|
||||
|`--drivers-import-chunk-size`|服务器启动时可以并行导入的最大驱动程序数量|number|`3`||
|
||||
|`--keep-alive-timeout`|Appium服务器应该将所有请求的保持活跃超时(keep-alive timeout)和连接超时(connection timeout)都设置为多少秒。如果将其设置为0,则会禁用超时设置。|integer|`600`|`-ka`|
|
||||
|`--local-timezone`|使用本地时区来记录时间戳|boolean|`false`||
|
||||
|`--log`|同时将日志输出发送到文件|string||`-g`|
|
||||
|`--log-filters`|一个或多个日志过滤规则|array|||
|
||||
|`--log-level`|日志级别(console[:file]),值必须是以下之一:`info`, `info:debug`, `info:info`, `info:warn`, `info:error`, `warn`, `warn:debug`, `warn:info`, `warn:warn`, `warn:error`, `error`, `error:debug`, `error:info`, `error:warn`, `error:error`, `debug`, `debug:debug`, `debug:info`, `debug:warn`, `debug:error`)|string|`debug`||
|
||||
|`--log-format`|日志格式(值必须是以下之一:`text`, `json`, `pretty_json`)。如果日志以JSON格式打印,则会始终禁用文本着色。|string|`text`||
|
||||
|`--log-no-colors`|不要在控制台输出中使用颜色|boolean|`false`||
|
||||
|`--log-timestamp`|在控制台输出中显示时间戳|boolean|`false`||
|
||||
|`--long-stacktrace`|在日志条目中添加长堆栈跟踪,建议仅用于调试|boolean|`false`||
|
||||
|`--no-perms-check`|跳过服务器启动时的各种权限检查|boolean|`false`||
|
||||
|`--nodeconfig`|将Appium注册为Selenium Grid 3节点的JSON配置文件的路径;否则配置本身|string|||
|
||||
|`--plugin`|插件特定配置,键名应与插件包名称相对应|object|||
|
||||
|`--plugins-import-chunk-size`|服务器启动时可以并行导入的插件的最大数量|number|`7`||
|
||||
|`--port`|要监听的端口(值必须介于`1`和`65535`之间)|integer|`4723`|`-p`|
|
||||
|`--relaxed-security`|禁用附加的安全检查,以便使用支持此选项的驱动程序提供的一些高级功能。只有当所有客户端都在受信任的网络中时才启用它,如果客户端有可能脱离会话沙盒,则不会启用它。可以使用`--deny-insecure`覆盖特定功能|boolean|`false`||
|
||||
|`--session-override`|启用会话覆盖(覆盖现有会话)|boolean|`false`||
|
||||
|`--ssl-cert-path`|如果使用TLS,则指向`.cert`文件的绝对路径。必须与`--ssl-key-path`一起使用。有关详细信息,请参阅[SSL/TLS/SPDY支持指南](../guides/tls.md)|string|||
|
||||
|`--ssl-key-path`|如果使用TLS,则指向`.key`文件的绝对路径。必须与`--ssl-cert-path`一起使用。有关详细信息,请参阅[SSL/TLS/SPDY支持指南](../guides/tls.md)|string|||
|
||||
|`--strict-caps`|如果发送了Appium认为对于选定设备无效的能力则使会话失败。|boolean|`false`||
|
||||
|`--tmp`|Appium可用于管理临时文件的目录的绝对路径|string|Windows: `C:\Windows\Temp`<br>其他: `/tmp`||
|
||||
|`--trace-dir`|Appium用于保存iOS Instruments跟踪数据的目录的绝对路径|string|`<tmp>/appium-instruments`||
|
||||
|`--use-drivers`|要激活的驱动程序列表,默认情况下,所有已安装的驱动程序都将被激活|array<string>|`[]`||
|
||||
|`--use-plugins`|要激活的插件列表,要激活所有插件,该值应该是一个包含单个项`"all"`的数组|array<string>|`[]`||
|
||||
|`--webhook`|同时将日志输出发送到此http侦听器|string||`-G`|
|
||||
|
||||
The following arguments are used for information retrieval, after which the server will automatically exit. They are therefore meant for reference or debug purposes.
|
||||
以下参数用于信息检索,运行之后服务器将自动退出。因此,它们仅供参考或调试使用。
|
||||
|
||||
|<div style="width:10em">Argument</div>|Description|Alias|
|
||||
|--|--|--|
|
||||
|`--help`|Print instructions on using the Appium command-line. This argument can also be used for any Appium subcommands.|`-h`|
|
||||
|`--show-build-info`|Print detailed information on the Appium server version||
|
||||
|`--show-config`|Print the current Appium server configuration details||
|
||||
|`--show-debug-info`|Print information on the current environment: details about the operating system, Node.js, and Appium itself||
|
||||
|`--version`|Print the Appium server version|`-v`|
|
||||
|`--help`|打印使用Appium命令行的说明,此参数也可用于Appium子命令|`-h`|
|
||||
|`--show-build-info`|打印Appium服务器版本的详细信息||
|
||||
|`--show-config`|打印当前Appium服务器配置详细信息||
|
||||
|`--show-debug-info`|打印当前环境的信息:操作系统、Node.js和Appium本身的详细信息||
|
||||
|`--version`|打印Appium服务器版本|`-v`|
|
||||
|
||||
@@ -2,25 +2,21 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Server Environment Variables
|
||||
title: 服务器环境变量
|
||||
---
|
||||
|
||||
The primary way of configuring the Appium server is via [Command-Line Arguments](./args.md). However, some more
|
||||
advanced features are toggled or configured via environment variables. To set environment
|
||||
variables, refer to the documentation for your operating system and terminal. These are the
|
||||
environment variables that the Appium server understands:
|
||||
配置Appium服务器的主要方式是通过[命令行参数](./args.md)。然而,一些更高级的功能是通过环境变量切换或配置的。
|
||||
要设置环境变量,请参阅操作系统和终端的文档。这些是Appium服务器能够理解的环境变量:
|
||||
|
||||
|Variable |Description|
|
||||
|变量 |描述|
|
||||
|--------|-----------|
|
||||
|`APPIUM_HOME`|By default, Appium creates a directory called `.appium` in the home directory for your system user. You can adjust the directory with this variable, as detailed in the [Managing Extensions](../guides/managing-exts.md) guide.|
|
||||
|`APPIUM_TMP_DIR`|By default, Appium uses a random temporary directory for many of its operations. If you wish to use a specific directory, you may do so by including an absolute path as the value of this variable. The behaviour is equivalent to using the `--tmp` CLI arg.|
|
||||
|`APPIUM_PREFER_SYSTEM_UNZIP`|Set to `0` or `false` to request that Appium not use the `unzip` binary included on your system for unzipping downloaded apps or other artifacts. Instead it will use a JS-based unzip library. This could help on some systems with non-existent or non-standard `unzip` commands. Note that if unzipping fails using the system library, the fallback library will be attempted in any case, so setting this env var merely saves time in the event you know the system unzip will fail.|
|
||||
|`APPIUM_HOST`|Same as the `--address` CLI arg|
|
||||
|`APPIUM_PORT`|Same as the `--port` CLI arg|
|
||||
|`APPIUM_RELOAD_EXTENSIONS`|Set to `1` to cause Appium to re-require extensions when new sessions are created. This is mostly useful for [building extensions](../developing/build-drivers.md)|
|
||||
|`APPIUM_OMIT_PEER_DEPS`|Adds `--omit=peer` to all the NPM commands run internally by Appium. Mostly an internal feature.|
|
||||
|`APPIUM_APPS_CACHE_MAX_AGE`|Allows to set the maximum age (in minutes) for [cached applications](../guides/caching.md). The default value is `60 * 24` (24 hours). Do not set it to a lower number than the duration of a single session startup.|
|
||||
|`APPIUM_APPS_CACHE_MAX_ITEMS`|Allows to set the maximum amount of [cached applications](../guides/caching.md). The default value is `1024`. Do not set it to a lower number than the amount of apps in all parallel sessions per process.|
|
||||
|`APPIUM_APPS_CACHE_IGNORE_URL_QUERY`| If the above option is enabled then the 'search' part of the app URL will be cut off from cache keys. See the corresponding
|
||||
[feature request](https://discuss.appium.io/t/regarding-app-caching-when-using-aws-s3-presigned-urls/42713)
|
||||
for more details. Disabled by default.|
|
||||
|`APPIUM_HOME`|默认情况下,Appium会在系统用户的主目录中创建一个名为`.appium`的目录。您可以使用此变量调整目录,详见[管理扩展](../guides/managing-exts.md)指南。|
|
||||
|`APPIUM_TMP_DIR`|默认情况下,Appium的许多操作都使用随机临时目录。如果您希望使用特定目录,可以通过将绝对路径作为此变量的值来实现。该行为相当于使用`--tmp`CLI参数。|
|
||||
|`APPIUM_PREFER_SYSTEM_UNZIP`|设置为0或false,以要求Appium不要使用系统中包含的unzip二进制文件来解压下载的应用程序或其他文件,而去使用基于JS的unzip库;这有助于解决一些系统中不存在或存在非标准的unzip命令的问题。请注意,如果使用系统库解压失败,无论如何都会尝试回退库,所以设置这个环境变量只是在你知道系统unzip会失败的情况下节省时间。|
|
||||
|`APPIUM_HOST`|与`--address`CLI参数相同|
|
||||
|`APPIUM_PORT`|与`--port`CLI参数相同|
|
||||
|`APPIUM_RELOAD_EXTENSIONS`|设置为1可使Appium在创建新会话时重新加载扩展,这主要适用于[构建扩展](../developing/build-drivers.md)|
|
||||
|`APPIUM_OMIT_PEER_DEPS`|将`--omit=peer`添加到Appium内部运行的所有NPM命令中,主要是内部特征。|
|
||||
|`APPIUM_APPS_CACHE_MAX_AGE`|允许设置[缓存应用程序](../guides/caching.md)的最长使用时间(以分钟为单位),默认值为60*24(24小时);不要将其设置为低于单个会话启动持续时间的数字。|
|
||||
|`APPIUM_APPS_CACHE_MAX_ITEMS`|允许设置[缓存应用程序](../guides/caching.md)的最大数量,默认值为`1024`;不要将其设置为低于每个进程所有并行会话中的应用程序数量。|
|
||||
|`APPIUM_APPS_CACHE_IGNORE_URL_QUERY`|如果启用此选项,则应用程序URL中的“搜索”部分将被忽略;有关更多详细信息,请参阅相应的[内容](https://discuss.appium.io/t/regarding-app-caching-when-using-aws-s3-presigned-urls/42713);默认情况下禁用。|
|
||||
|
||||
@@ -1,58 +1,50 @@
|
||||
---
|
||||
title: Extension Command-Line Usage
|
||||
title: 扩展命令行用法
|
||||
---
|
||||
|
||||
Appium allows for the flexible installation and management of various _extensions_, such as _drivers_
|
||||
(which provide Appium with the capability to automate a given platform) and _plugins_ (which can
|
||||
augment or alter the way individual Appium commands work). For a conceptual understanding of these
|
||||
entities, please review the [Introduction](../intro/index.md).
|
||||
Appium允许灵活安装和管理各种扩展,例如驱动程序(为Appium提供自动化给定平台的能力)和插件(可以增强或改变单个Appium命令的工作方式)。
|
||||
要从概念上理解这些实体,请查看[引言](../intro/index.md)。
|
||||
|
||||
Management of drivers and plugins is handled by Appium's Extension CLI (command-line interface).
|
||||
驱动程序和插件的管理由Appium的扩展命令行处理。
|
||||
|
||||
!!! note
|
||||
!!! 注意
|
||||
|
||||
This reference uses placeholders to refer to various options. Anywhere you see one of these
|
||||
placeholders in the reference, ensure you replace it with the correct type of actual content.
|
||||
|
||||
|Placeholder|Meaning|
|
||||
这篇文档使用了占位符来指代各种选项。在参考文档中,任何时候你看到这些占位符,确保你用正确的实际内容替换它们。
|
||||
|
||||
|占位符|含义|
|
||||
|--|--|
|
||||
|`<ext-type>`|"Extension type". It should be either `driver` or `plugin`. All the Extension CLI commands can be used with either drivers or plugins, so you must specify which type of extension will be used|
|
||||
|`<ext-name>`|"Extension name". This is the short name of the extension found in a call to `appium <ext-type> list`. This is distinct from the NPM package name of the extension or, in general, the "install spec" of the extension.|
|
||||
|`<install-spec>`|"Install specification". This refers to the string used to indicate what extension Appium should install.|
|
||||
|`<install-source>`|This refers to the method that Appium should use to install an extension.|
|
||||
|`<ext-type>`|"Extension type",它应该是`driver`或`plugin`;所有的扩展命令行都可以与驱动程序或插件一起使用,因此您必须指定将使用哪种类型的扩展。|
|
||||
|`<ext-name>`|"Extension name",这是对`appium <ext-type> list`的调用中找到的扩展名的简称;这与扩展的NPM包名不同,或者通常来说,与扩展的“安装规范”是有所区别的。|
|
||||
|`<install-spec>`|"Install specification",这是指用于指示Appium应安装什么扩展的字符串。|
|
||||
|`<install-source>`|这是指Appium安装扩展程序应该使用的方法。|
|
||||
|
||||
## Commands
|
||||
## 命令
|
||||
|
||||
All Extension CLI commands begin with `appium <ext-type>`, i.e., either `appium driver` or `appium
|
||||
plugin`.
|
||||
所有扩展命令行都以`appium <ext-type>`开头,即 `appium driver`或`appium plugin`。
|
||||
|
||||
All Extension CLI commands can take an optional `--json` argument, which will return the result of
|
||||
the command as a machine-readable JSON string rather than the standard output, which is colourized
|
||||
and tuned for human consumption.
|
||||
所有扩展命令行都可以接受一个可选的`--json`参数,这个参数会让命令的输出结果以机器可读的JSON字符串形式返回,而不是标准的、为人类阅读优化的、带颜色的输出。
|
||||
|
||||
### `doctor`
|
||||
|
||||
Run doctor checks for the given extension, which validate whether the extension has its prerequisites
|
||||
configured correctly. Note that not all extensions include doctor checks. See the
|
||||
[Building Doctor Checks](../developing/build-doctor-checks.md) tutorial for more details on
|
||||
how to create them.
|
||||
运行给定扩展的医生检查,以验证扩展的先决条件是否配置正确。请注意,并非所有的扩展都包含医生检查工具。
|
||||
有关如何创建它们的更多详细信息,请参阅[构建检查工具](../developing/build-doctor-checks.md)教程。
|
||||
|
||||
Usage:
|
||||
使用方法:
|
||||
|
||||
```
|
||||
appium <ext-type> doctor <ext-name>
|
||||
```
|
||||
|
||||
Required arguments:
|
||||
必须的参数:
|
||||
|
||||
- `<ext-type>`: must be `driver` or `plugin`
|
||||
- `<ext-name>`: the name of the extension whose doctor checks you want to run
|
||||
- `<ext-type>`:必须为`driver`或`plugin`
|
||||
- `<ext-name>`:您要运行医生检查的扩展名
|
||||
|
||||
Optional arguments:
|
||||
可选的参数:
|
||||
|
||||
- `--json`: return the result in JSON format
|
||||
- `--json`:以JSON格式返回结果
|
||||
|
||||
Example (run doctor checks for the UiAutomator2 driver):
|
||||
示例(运行UiAutomator2驱动程序的医生检查):
|
||||
|
||||
```
|
||||
appium driver doctor uiautomator2
|
||||
@@ -60,71 +52,63 @@ appium driver doctor uiautomator2
|
||||
|
||||
### `install`
|
||||
|
||||
Install an extension. If successful, respond with the short name of the extension which can be used
|
||||
in other invocations of the Extension CLI. If the extension is a driver, also note which platforms
|
||||
may be used with the driver.
|
||||
安装一个扩展。如果安装成功,返回扩展的短名称,这个短名称可以在其他扩展命令行的调用中使用。如果扩展是一个驱动程序,还应该注明可以使用该驱动程序的平台。
|
||||
|
||||
Usage:
|
||||
使用方法:
|
||||
|
||||
```
|
||||
appium <ext-type> install <install-spec> [--source=<install-source>] [--package=<package-name>] [--json]
|
||||
```
|
||||
|
||||
Required arguments:
|
||||
必须的参数:
|
||||
|
||||
- `<ext-type>`: must be `driver` or `plugin`
|
||||
- `<install-spec>`: this is the name, location, and/or version of the extension you want to
|
||||
install. Its possible values are dependent on the `<install-source>` (see below).
|
||||
- `<ext-type>`:必须为`driver`或`plugin`
|
||||
- `<install-spec>`:这是您要安装的扩展的名称、位置或版本。其可能的值取决于`<install-source>`(见下文)。
|
||||
|
||||
Optional arguments:
|
||||
可选的参数:
|
||||
|
||||
- `--source`: this directs Appium where to find your extension. See below for a table of possible
|
||||
source types and corresponding install specification.
|
||||
- `--package`: when `<install-source>` is `git` or `github`, `--package` is required. It should be
|
||||
the Node.js package name of the extension. Without this information, Appium will not be able to
|
||||
find the installed package.
|
||||
- `--json`: return the result in JSON format
|
||||
- `--source`:告诉Appium如何定位您的扩展;查看下面的表格,了解可能的来源类型和相应的安装规范。
|
||||
- `--package`:当`<install-source>`的值为`git`或`github`,`--package`参数是必须的. 它必须是扩展的Node.js包名称。缺少这些信息的话,Appium将无法定位到已安装的包。
|
||||
- `--json`:以JSON格式返回结果
|
||||
|
||||
|Install source type|Behaviour|
|
||||
|安装源类型|行为|
|
||||
|--|--|
|
||||
|None|This is the default behaviour when no `--source` is used. In this case, Appium will look at `<install-spec>` and match it against the name of extensions available when running `appium <ext-type> list`, i.e., against the officially recognized extension names. If found, it will install that extension at the latest version via NPM|
|
||||
|`npm`|Install an extension based on its NPM package name. Here, `<install-spec>` must be the NPM package name with any additional NPM installation modifiers, like version (see below)|
|
||||
|`github`|Install an extension via a GitHub spec of the form `<org>/<repo>`|
|
||||
|`git`|Install an extension via a Git URL (e.g., `git+ssh://git-host.com/repo.git`)|
|
||||
|`local`|Install an extension via a local path. This must be a path to the directory where the Node.js package information for the driver is located.|
|
||||
|None|如果不使用`--source`选项,Appium将执行默认操作。此时,Appium会检查`<install-spec>`并将其与执行`appium <ext-type> list`命令时列出的扩展名称进行匹配,也就是与官方认可的扩展名称进行匹配。如果匹配成功,Appium将通过NPM安装该扩展的最新版本。|
|
||||
|`npm`|根据扩展的NPM包名来安装扩展。在这里,`<install-spec>`必须包含NPM包名以及任何附加的NPM安装修饰符,例如版本号(参见下文)。|
|
||||
|`github`|通过`<org>/<repo>`格式的GitHub规范安装扩展|
|
||||
|`git`|通过Git URL安装扩展(例如:`git+ssh://git-host.com/repo.git`)|
|
||||
|`local`|通过本地路径安装扩展。这必须是驱动程序的Node.js包信息所在目录的路径。|
|
||||
|
||||
#### NPM-based `<install-spec>`
|
||||
#### 基于NPM安装 `<install-spec>`
|
||||
|
||||
When Appium is installing an extension via NPM (as is the case when `--source` is either omitted or
|
||||
set to `npm`), the `<install-spec>` can be complex, and can include any kind of information allowed
|
||||
by `npm install`:
|
||||
当Appium通过NPM安装扩展(即当`--source`参数被省略或设置为`npm`时),`<install-spec>`可以非常复杂,并且可以包括`npm install`所允许的任何形式的信息:
|
||||
|
||||
- `[@scope]/<name>`
|
||||
- `[@scope]/<name>@<version>`
|
||||
- `[@scope]/<name>@<tag>`
|
||||
- `[@scope]/<name>@<version range>`
|
||||
|
||||
#### Examples
|
||||
#### 示例
|
||||
|
||||
- Install the latest XCUITest driver:
|
||||
- 安装最新的XCUITest驱动程序:
|
||||
|
||||
```
|
||||
appium driver install xcuitest
|
||||
```
|
||||
|
||||
- Install the XCUITest driver at version 4.11.1:
|
||||
- 安装4.11.1版本的XCUITest驱动程序:
|
||||
|
||||
```
|
||||
appium driver install xcuitest@4.11.1
|
||||
```
|
||||
|
||||
- Install the `beta` version of the `@appium/fake-driver` from NPM:
|
||||
- 从NPM安装`beta`版本的`@appium/fake-driver`:
|
||||
|
||||
```
|
||||
appium driver install --source=npm @appium/fake-driver@beta
|
||||
```
|
||||
|
||||
- Install a locally-developed plugin:
|
||||
- 安装本地开发的插件:
|
||||
|
||||
```
|
||||
appium plugin install --source=local /path/to/my/plugin
|
||||
@@ -132,52 +116,46 @@ by `npm install`:
|
||||
|
||||
### `list`
|
||||
|
||||
List installed and available extensions. "Available" extensions include those which are officially
|
||||
recognized by the Appium team, but you are not limited to installing only the extensions displayed
|
||||
in this list.
|
||||
列出已安装和可用的扩展。可用扩展包括Appium团队正式认可的扩展,但您不仅限于安装此列表中显示的扩展。
|
||||
|
||||
Usage:
|
||||
使用方法:
|
||||
|
||||
```
|
||||
appium <ext-type> list [--installed] [--updates] [--json]
|
||||
```
|
||||
|
||||
Required arguments:
|
||||
必须的参数:
|
||||
|
||||
- `<ext-type>`: must be `driver` or `plugin`
|
||||
- `<ext-type>`:必须为`driver`或`plugin`
|
||||
|
||||
Optional arguments:
|
||||
可选的参数:
|
||||
|
||||
- `--installed`: show only installed extensions, not installed plus available extensions
|
||||
- `--updates`: for extensions installed via NPM, display a message if there are any updates
|
||||
- `--json`: return the result in JSON format
|
||||
- `--installed`:仅显示已安装的扩展程序,而不是已安装和可用的扩展程序
|
||||
- `--updates`:对于通过NPM安装的扩展,如果有任何更新,则显示一条消息
|
||||
- `--json`:以JSON格式返回结果
|
||||
|
||||
### `run`
|
||||
|
||||
Run a script included in an extension package. Extension authors can include runnable scripts that
|
||||
assist with setup or perform other tasks. These scripts are given names (called the `<script-name>`
|
||||
in this reference) by extension authors and will generally be documented in extension
|
||||
documentation.
|
||||
运行扩展包中包含的脚本。扩展作者可以包含可运行的脚本,以协助设置或执行其他任务。这些脚本由扩展作者命名(本指南中称为`<script-name>`),通常会在扩展文档中加以说明。
|
||||
|
||||
Usage:
|
||||
使用方法:
|
||||
|
||||
```
|
||||
appium <ext-type> run <ext-name> [--json] <script-name> [script-args]
|
||||
```
|
||||
|
||||
Required arguments:
|
||||
必须的参数:
|
||||
|
||||
- `<ext-type>`: must be `driver` or `plugin`
|
||||
- `<ext-name>`: the name of the extension whose script you want to run
|
||||
- `<script-name>`: the name of the script the extension has published
|
||||
- `<ext-type>`:必须为`driver`或`plugin`
|
||||
- `<ext-name>`:要运行脚本的扩展名
|
||||
- `<script-name>`:扩展发布的脚本的名称
|
||||
|
||||
Optional arguments:
|
||||
可选的参数:
|
||||
|
||||
- `script-args`: any arguments that Appium does not interpret as belonging to its own set of
|
||||
arguments will be passed along to the extension script
|
||||
- `--json`: return the result in JSON format
|
||||
- `script-args`:任何Appium无法识别为其自身参数集的参数,都将传递给扩展脚本
|
||||
- `--json`:以JSON格式返回结果
|
||||
|
||||
Example (run the `reset` script included with the UiAutomator2 driver):
|
||||
示例(运行UiAutomator2驱动程序附带的`reset`脚本):
|
||||
|
||||
```
|
||||
appium driver run uiautomator2 reset
|
||||
@@ -185,42 +163,39 @@ appium driver run uiautomator2 reset
|
||||
|
||||
### `update`
|
||||
|
||||
Update one or more extensions that have been installed via NPM. By default, Appium will not
|
||||
automatically update any extension past a major version boundary, so as to prevent
|
||||
unintended breaking changes.
|
||||
更新通过NPM安装的一个或多个扩展。默认情况下,Appium不会自动更新超过主要版本边界的任何扩展,以防止意外的破坏性更改。
|
||||
|
||||
Usage:
|
||||
使用方法:
|
||||
|
||||
```
|
||||
appium <ext-type> update <ext-name> [--unsafe] [--json]
|
||||
```
|
||||
|
||||
Required arguments:
|
||||
必须的参数:
|
||||
|
||||
- `<ext-type>`: must be `driver` or `plugin`
|
||||
- `<ext-name>`: the name of the extension to update, or the string `installed` (which will update
|
||||
all installed extensions)
|
||||
- `<ext-type>`:必须为`driver`或`plugin`
|
||||
- `<ext-name>`:要更新的扩展名或已安装的字符串(将更新所有已安装的扩展)
|
||||
|
||||
Optional arguments:
|
||||
可选的参数:
|
||||
|
||||
- `--unsafe`: direct Appium to go ahead and update past a major version boundary
|
||||
- `--json`: return the result in JSON format
|
||||
- `--unsafe`:允许Appium更新到超越主要版本界限的版本
|
||||
- `--json`:以JSON格式返回结果
|
||||
|
||||
### `uninstall`
|
||||
|
||||
Remove an installed extension.
|
||||
删除已安装的扩展。
|
||||
|
||||
Usage:
|
||||
使用方法:
|
||||
|
||||
```
|
||||
appium <ext-type> uninstall <ext-name> [--json]
|
||||
```
|
||||
|
||||
Required arguments:
|
||||
必须的参数:
|
||||
|
||||
- `<ext-type>`: must be `driver` or `plugin`
|
||||
- `<ext-name>`: the name of the extension to uninstall
|
||||
- `<ext-type>`:必须为`driver`或`plugin`
|
||||
- `<ext-name>`:要卸载的扩展程序的名称
|
||||
|
||||
Optional arguments:
|
||||
可选的参数:
|
||||
|
||||
- `--json`: return the result in JSON format
|
||||
- `--json`:以JSON格式返回结果
|
||||
|
||||
@@ -2,25 +2,23 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Command-Line Overview
|
||||
title: 命令行概述
|
||||
---
|
||||
|
||||
Appium provides a command-line executable (`appium`), which will likely be your main way of interacting with
|
||||
the Appium server. This section of the Appium documentation describes how to use this executable.
|
||||
Appium提供了一个命令行可执行文件(`appium`),这可能是您与Appium服务器交互的主要方式。这一部分的文档描述了如何使用此可执行文件。
|
||||
|
||||
To start off, you can run `appium -v` or `appium --version` to return the installed version,
|
||||
or run `appium -h` or `appium --help` to return the help message.
|
||||
首先,您可以运行`appium -v`或`appium --version`返回已安装的版本信息,或运行`appium -h`或`appium --help`返回帮助信息。
|
||||
|
||||
The main `appium` executable provides the following subcommands:
|
||||
主命令`appium`可提供以下子命令:
|
||||
|
||||
1. `appium server` (or simply `appium`) - launch an Appium server
|
||||
- [See here for accepted arguments](./args.md)
|
||||
- For advanced features, [see here for accepted environment variables](./env-vars.md)
|
||||
2. `appium driver` - manage Appium drivers
|
||||
- [See here for details](./extensions.md)
|
||||
3. `appium plugin` - manage Appium plugins
|
||||
- [See here for details](./extensions.md)
|
||||
4. `appium setup` - batch install a preset of drivers and plugins
|
||||
- [See here for details](./setup.md)
|
||||
1. `appium server` (或 `appium`) - 启动appium服务器
|
||||
- [请查看此处了解可接受的参数](./args.md)
|
||||
- 有关高级功能,[请查看此处了解支持的环境变量](./env-vars.md)
|
||||
2. `appium driver` - 管理Appium驱动
|
||||
- [详情请查看此处](./extensions.md)
|
||||
3. `appium plugin` - 管理Appium插件
|
||||
- [详情请查看此处](./extensions.md)
|
||||
4. `appium setup` - 批量安装预设的驱动程序和插件
|
||||
- [详情请查看此处](./setup.md)
|
||||
|
||||
Like the main command, you can also run each subcommand with the `-h` or `--help` flag to learn more about it.
|
||||
与主命令一样,您也可以使用`-h`或`--help`标志运行每个子命令以了解更多信息。
|
||||
|
||||
@@ -2,27 +2,22 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Setup Command-Line Usage
|
||||
title: 设置命令行用法
|
||||
---
|
||||
|
||||
The `setup` command aims to simplify the initial procedure of setting up Appium. It allows to install
|
||||
multiple extensions (drivers/plugins) in one go, without the need to run
|
||||
`appium <ext-name> install <ext-name>` multiple times.
|
||||
`setup`命令旨在简化Appium的初始设置过程。它允许一次性安装多个扩展(驱动程序/插件),而无需多次运行`appium <ext-name> install <ext-name>`。
|
||||
|
||||
The command has several presets that can be used to install different sets of extensions.
|
||||
The presets are as follows:
|
||||
该命令具有多个预设,可用于安装不同组合的扩展。这些预设如下:
|
||||
|
||||
|Preset|Installation Command|Included Drivers|Included Plugins|
|
||||
|预设|安装命令|包含的驱动|包含的插件|
|
||||
|--|--|--|--|
|
||||
|Mobile|`appium setup mobile` or `appium setup`|`uiautomator2`, `xcuitest`[^1], `espresso`|`images`|
|
||||
|Desktop application|`appium setup desktop`|`mac2`[^1], `windows`[^2]|`images`|
|
||||
|Desktop browser|`appium setup browser`|`safari`[^1], `gecko`, `chromium`|`images`|
|
||||
|手机端应用程序|`appium setup mobile` or `appium setup`|`uiautomator2`, `xcuitest`[^1], `espresso`|`images`|
|
||||
|桌面端应用程序|`appium setup desktop`|`mac2`[^1], `windows`[^2]|`images`|
|
||||
|桌面端浏览器|`appium setup browser`|`safari`[^1], `gecko`, `chromium`|`images`|
|
||||
|
||||
Attempting to install a preset while already having one or more of its included extensions installed
|
||||
will only install the missing extensions.
|
||||
在已安装一个或多个预设包含的扩展的情况下尝试安装预设,将只安装缺少的扩展。
|
||||
|
||||
Refer to the [Ecosystem documentation](../ecosystem/index.md) to learn more about the extensions
|
||||
listed above.
|
||||
请参阅[生态系统](../ecosystem/index.md)文档,了解有关扩展的更多信息。
|
||||
|
||||
[^1]: Only installed if the host machine is running macOS.
|
||||
[^2]: Only installed if the host machine is running Windows.
|
||||
[^1]: 仅在主机运行macOS时才安装。
|
||||
[^2]: 仅在主机运行Windows时才安装。
|
||||
|
||||
@@ -1,235 +1,229 @@
|
||||
# Driver: base-driver
|
||||
# 驱动: base-driver
|
||||
|
||||
### `createSession`
|
||||
|
||||
`POST` **`/session`**
|
||||
|
||||
Historically the first two arguments were reserved for JSONWP capabilities.
|
||||
Appium 2 has dropped the support of these, so now we only accept capability
|
||||
objects in W3C format and thus allow any of the three arguments to represent
|
||||
the latter.
|
||||
从历史上看,前两个参数是专门用于JSONWP功能的,但是Appium2已经放弃了对这些参数的支持。
|
||||
现在我们只接受W3C格式的功能对象,这种对象可以通过三个参数中的任意一个来传递。
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#new-session](https://w3c.github.io/webdriver/#new-session)
|
||||
|
||||
<!-- comment source: multiple -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `desiredCapabilities?` | `W3CDriverCaps`<`C`\> | the new session capabilities |
|
||||
| `requiredCapabilities?` | `W3CDriverCaps`<`C`\> | another place the new session capabilities could be sent (typically left undefined) |
|
||||
| `capabilities?` | `W3CDriverCaps`<`C`\> | another place the new session capabilities could be sent (typically left undefined) |
|
||||
| `desiredCapabilities?` | `W3CDriverCaps`<`C`\> | 新的会话功能 |
|
||||
| `requiredCapabilities?` | `W3CDriverCaps`<`C`\> | 另一个可以发送新会话功能的地方(通常未定义) |
|
||||
| `capabilities?` | `W3CDriverCaps`<`C`\> | 另一个可以发送新会话功能的地方(通常未定义) |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`CreateResult`
|
||||
|
||||
The capabilities object representing the created session
|
||||
表示所创建会话的能力对象
|
||||
|
||||
### `deleteSession`
|
||||
|
||||
`DELETE` **`/session/:sessionId`**
|
||||
|
||||
Returns capabilities for the session and event history (if applicable)
|
||||
返回会话和事件历史记录的功能(如果可用)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`SingularSessionData`<`C`, `SessionData`\>
|
||||
|
||||
A session data object
|
||||
会话数据对象
|
||||
|
||||
### `getSession`
|
||||
|
||||
`GET` **`/session/:sessionId`**
|
||||
|
||||
Returns capabilities for the session and event history (if applicable)
|
||||
返回会话和事件历史记录的功能(如果可用)
|
||||
|
||||
<!-- comment source: multiple -->
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`SingularSessionData`<`C`, `SessionData`\>
|
||||
|
||||
A session data object
|
||||
会话数据对象
|
||||
|
||||
### `findElement`
|
||||
|
||||
`POST` **`/session/:sessionId/element`**
|
||||
|
||||
Find a UI element given a locator strategy and a selector, erroring if it can't be found
|
||||
在给定定位策略和选择器的情况下查找UI元素,如果找不到则报错
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-element](https://w3c.github.io/webdriver/#find-element)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `string` | the locator strategy |
|
||||
| `value` | `string` | the selector to combine with the strategy to find the specific element |
|
||||
| `using` | `string` | 定位策略 |
|
||||
| `value` | `string` | 选择器与策略相结合,找到特定元素 |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`Element`<`string`\>
|
||||
|
||||
The element object encoding the element id which can be used in element-related
|
||||
commands
|
||||
对元素id进行编码的元素对象,可用于元素相关命令
|
||||
|
||||
### `findElementFromElement`
|
||||
|
||||
`POST` **`/session/:sessionId/element/:elementId/element`**
|
||||
|
||||
Find a UI element given a locator strategy and a selector, erroring if it can't be found. Only
|
||||
look for elements among the set of descendants of a given element
|
||||
在给定定位策略和选择器的情况下查找UI元素,如果找不到则会报错,仅在给定元素的子元素中查找。
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-element-from-element](https://w3c.github.io/webdriver/#find-element-from-element)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `string` | the locator strategy |
|
||||
| `value` | `string` | the selector to combine with the strategy to find the specific element |
|
||||
| `using` | `string` | 定位策略 |
|
||||
| `value` | `string` | 选择器与策略相结合,找到特定元素 |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`Element`<`string`\>
|
||||
|
||||
The element object encoding the element id which can be used in element-related
|
||||
commands
|
||||
对元素id进行编码的元素对象,可用于元素相关命令
|
||||
|
||||
### `findElementFromShadowRoot`
|
||||
|
||||
`POST` **`/session/:sessionId/shadow/:shadowId/element`**
|
||||
|
||||
Find an element from a shadow root
|
||||
从阴影根中查找元素。
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-element-from-shadow-root](https://w3c.github.io/webdriver/#find-element-from-shadow-root)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `string` | the locator strategy |
|
||||
| `value` | `string` | the selector to combine with the strategy to find the specific elements |
|
||||
| `using` | `string` | 定位策略 |
|
||||
| `value` | `string` | 选择器与策略相结合,找到特定元素 |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`Element`<`string`\>
|
||||
|
||||
The element inside the shadow root matching the selector
|
||||
阴影根内与选择器匹配的元素
|
||||
|
||||
### `findElements`
|
||||
|
||||
`POST` **`/session/:sessionId/elements`**
|
||||
|
||||
Find a a list of all UI elements matching a given a locator strategy and a selector
|
||||
查找与给定定位策略和选择器匹配的所有UI元素的列表
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-elements](https://w3c.github.io/webdriver/#find-elements)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `string` | the locator strategy |
|
||||
| `value` | `string` | the selector to combine with the strategy to find the specific elements |
|
||||
| `using` | `string` | 定位策略 |
|
||||
| `value` | `string` | 选择器与策略相结合,找到特定元素 |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`Element`<`string`\>[]
|
||||
|
||||
A possibly-empty list of element objects
|
||||
仅在给定元素的子元素中查找。
|
||||
|
||||
### `findElementsFromElement`
|
||||
|
||||
`POST` **`/session/:sessionId/element/:elementId/elements`**
|
||||
|
||||
Find a a list of all UI elements matching a given a locator strategy and a selector. Only
|
||||
look for elements among the set of descendants of a given element
|
||||
查找与给定定位策略和选择器匹配的所有UI元素的列表,仅在给定元素的子元素中查找。
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-elements-from-element](https://w3c.github.io/webdriver/#find-elements-from-element)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `string` | the locator strategy |
|
||||
| `value` | `string` | the selector to combine with the strategy to find the specific elements |
|
||||
| `using` | `string` | 定位策略 |
|
||||
| `value` | `string` | 选择器与策略相结合,找到特定元素 |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`Element`<`string`\>[]
|
||||
|
||||
A possibly-empty list of element objects
|
||||
仅在给定元素的子元素中查找。
|
||||
|
||||
### `findElementsFromShadowRoot`
|
||||
|
||||
`POST` **`/session/:sessionId/shadow/:shadowId/elements`**
|
||||
|
||||
Find elements from a shadow root
|
||||
从阴影根中查找元素。
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-element-from-shadow-root](https://w3c.github.io/webdriver/#find-element-from-shadow-root)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `string` | the locator strategy |
|
||||
| `value` | `string` | the selector to combine with the strategy to find the specific elements |
|
||||
| `using` | `string` | 定位策略 |
|
||||
| `value` | `string` | 选择器与策略相结合,找到特定元素 |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`Element`<`string`\>[]
|
||||
|
||||
A possibly empty list of elements inside the shadow root matching the selector
|
||||
在阴影根内与选择器匹配的可能为空的元素列表。
|
||||
|
||||
### `getLog`
|
||||
|
||||
`POST` **`/session/:sessionId/log`**
|
||||
|
||||
Get the log for a given log type.
|
||||
获取给定日志类型的日志。
|
||||
|
||||
!!! warning "Deprecated"
|
||||
!!! warning "已弃用"
|
||||
|
||||
Please use the `/session/:sessionId/se/log` endpoint instead
|
||||
请使用`/session/:sessionId/se/log`代替
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `type` | `string` | Name/key of log type as defined in ILogCommands.supportedLogTypes. |
|
||||
| `type` | `string` | ILogCommands.supportedLogTypes中定义的日志类型的名称/密钥。 |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`any`
|
||||
|
||||
@@ -237,17 +231,17 @@ Get the log for a given log type.
|
||||
|
||||
`POST` **`/session/:sessionId/se/log`**
|
||||
|
||||
Get the log for a given log type.
|
||||
获取给定日志类型的日志。
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `type` | `string` | Name/key of log type as defined in ILogCommands.supportedLogTypes. |
|
||||
| `type` | `string` | ILogCommands.supportedLogTypes中定义的日志类型的名称/密钥。 |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`any`
|
||||
|
||||
@@ -255,35 +249,35 @@ Get the log for a given log type.
|
||||
|
||||
`POST` **`/session/:sessionId/appium/events`**
|
||||
|
||||
Get a list of events that have occurred in the current session
|
||||
获取当前会话中发生的事件列表。
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `type?` | `string` \| `string`[] | filter the returned events by including one or more types |
|
||||
| `type?` | `string` \| `string`[] | 通过包含一个或多个类型筛选返回的事件 |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`EventHistory` \| `Record`<`string`, `number`\>
|
||||
|
||||
The event history for the session
|
||||
会话的事件历史记录。
|
||||
|
||||
### `getLogTypes`
|
||||
|
||||
`GET` **`/session/:sessionId/log/types`**
|
||||
|
||||
Get available log types as a list of strings
|
||||
以字符串列表的形式获取可用日志类型。
|
||||
|
||||
!!! warning "Deprecated"
|
||||
!!! warning "已弃用"
|
||||
|
||||
Please use the `/session/:sessionId/se/log/types` endpoint instead
|
||||
请使用`/session/:sessionId/se/log/types`代替
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`string`[]
|
||||
|
||||
@@ -291,11 +285,11 @@ Get available log types as a list of strings
|
||||
|
||||
`GET` **`/session/:sessionId/se/log/types`**
|
||||
|
||||
Get available log types as a list of strings
|
||||
以字符串列表的形式获取可用日志类型。
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`string`[]
|
||||
|
||||
@@ -303,32 +297,31 @@ Get available log types as a list of strings
|
||||
|
||||
`GET` **`/session/:sessionId/source`**
|
||||
|
||||
Get the current page/app source as HTML/XML
|
||||
以HTML/XML格式获取当前页面/应用程序源代码。
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#get-page-source](https://w3c.github.io/webdriver/#get-page-source)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`string`
|
||||
|
||||
The UI hierarchy in a platform-appropriate format (e.g., HTML for a web page)
|
||||
以适合平台的格式呈现的用户界面层次结构(例如,对于网页使用HTML)。
|
||||
|
||||
### `getSessions`
|
||||
|
||||
`GET` **`/sessions`**
|
||||
|
||||
Get data for all sessions running on an Appium server
|
||||
获取Appium服务器上运行的所有会话的数据。
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
A list of session data objects.
|
||||
Each session data object will be returned with `id` and the session's capabilities as `capabilities` keys like an example below:
|
||||
会话数据对象列表。每个会话数据对象都将返回`id`和会话的功能作为`capabilities`键,如下所示:
|
||||
|
||||
```json
|
||||
[
|
||||
@@ -348,11 +341,11 @@ Each session data object will be returned with `id` and the session's capabiliti
|
||||
|
||||
`GET` **`/session/:sessionId/appium/settings`**
|
||||
|
||||
Update the session's settings dictionary with a new settings object
|
||||
使用新的设置对象更新会话的设置字典。
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
``null``
|
||||
|
||||
@@ -360,17 +353,17 @@ Update the session's settings dictionary with a new settings object
|
||||
|
||||
`POST` **`/session/:sessionId/appium/settings`**
|
||||
|
||||
Update the session's settings dictionary with a new settings object
|
||||
使用新的设置对象更新会话的设置字典。
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `settings` | `Settings` | A key-value map of setting names to values. Settings not named in the map will not have their value adjusted. |
|
||||
| `settings` | `Settings` | 一个包含设置名称和值的键值映射,映射中未列出的名称将不会修改其值。 |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
``null``
|
||||
|
||||
@@ -378,21 +371,21 @@ Update the session's settings dictionary with a new settings object
|
||||
|
||||
`GET` **`/status`**
|
||||
|
||||
**`Summary`**
|
||||
**`概述`**
|
||||
|
||||
Retrieve the server's current status.
|
||||
检索服务器的当前状态。
|
||||
|
||||
**`Description`**
|
||||
**`描述`**
|
||||
|
||||
Returns information about whether a remote end is in a state in which it can create new sessions and can additionally include arbitrary meta information that is specific to the implementation.
|
||||
返回关于远程端是否处于可以创建新会话的状态的信息,并且还可以包含特定于实现的任意元信息。
|
||||
|
||||
The readiness state is represented by the ready property of the body, which is false if an attempt to create a session at the current time would fail. However, the value true does not guarantee that a New Session command will succeed.
|
||||
就绪状态由主体的ready属性表示,如果当前尝试创建会话会失败,则该属性为false。然而值为true并不能保证新建会话命令一定会成功。
|
||||
|
||||
Implementations may optionally include additional meta information as part of the body, but the top-level properties ready and message are reserved and must not be overwritten.
|
||||
实现可以选择将额外的元信息作为主体的一部分包含进来,但顶级属性ready和message是保留的,并且不能被覆盖。
|
||||
|
||||
<!-- comment source: builtin-interface -->
|
||||
|
||||
#### Examples
|
||||
#### 示例
|
||||
|
||||
<!-- BEGIN:EXAMPLES -->
|
||||
##### JavaScript
|
||||
@@ -434,7 +427,7 @@ remote_status
|
||||
<!-- END:EXAMPLE -->
|
||||
<!-- END:EXAMPLES -->
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`Object`
|
||||
|
||||
@@ -442,15 +435,15 @@ remote_status
|
||||
|
||||
`GET` **`/session/:sessionId/timeouts`**
|
||||
|
||||
Set the various timeouts associated with a session
|
||||
设置与会话相关的各种超时。
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#set-timeouts](https://w3c.github.io/webdriver/#set-timeouts)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
``null``
|
||||
|
||||
@@ -458,25 +451,25 @@ Set the various timeouts associated with a session
|
||||
|
||||
`POST` **`/session/:sessionId/timeouts`**
|
||||
|
||||
Set the various timeouts associated with a session
|
||||
设置与会话相关的各种超时。
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#set-timeouts](https://w3c.github.io/webdriver/#set-timeouts)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `type?` | `string` | used only for the old (JSONWP) command, the type of the timeout |
|
||||
| `ms?` | `string` \| `number` | used only for the old (JSONWP) command, the ms for the timeout |
|
||||
| `script?` | `number` | the number in ms for the script timeout, used for the W3C command |
|
||||
| `pageLoad?` | `number` | the number in ms for the pageLoad timeout, used for the W3C command |
|
||||
| `implicit?` | `string` \| `number` | the number in ms for the implicit wait timeout, used for the W3C command |
|
||||
| `type?` | `string` | 仅用于旧的(JSONWP)命令,超时的类型 |
|
||||
| `ms?` | `string` \| `number` | 仅用于旧的(JSONWP)命令,表示超时的毫秒数 |
|
||||
| `script?` | `number` | 用于W3C命令的脚本超时时间(以毫秒为单位) |
|
||||
| `pageLoad?` | `number` | 用于W3C命令的页面加载超时时间(以毫秒为单位) |
|
||||
| `implicit?` | `string` \| `number` | 用于W3C命令的隐式等待超时时间(以毫秒为单位) |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
``null``
|
||||
|
||||
@@ -484,23 +477,23 @@ Set the various timeouts associated with a session
|
||||
|
||||
`POST` **`/session/:sessionId/timeouts/implicit_wait`**
|
||||
|
||||
Set the implicit wait timeout
|
||||
设置隐式等待超时时间
|
||||
|
||||
!!! warning "Deprecated"
|
||||
!!! warning "已弃用"
|
||||
|
||||
Please use the `/session/:sessionId/timeouts` endpoint instead
|
||||
请使用`/session/:sessionId/timeouts`代替
|
||||
|
||||
Use `timeouts` instead
|
||||
使用`timeouts`代替
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `ms` | `string` \| `number` | the timeout in ms |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
``null``
|
||||
|
||||
@@ -508,18 +501,18 @@ Use `timeouts` instead
|
||||
|
||||
`POST` **`/session/:sessionId/appium/log_event`**
|
||||
|
||||
Add a custom-named event to the Appium event log
|
||||
将自定义命名事件添加到Appium事件日志中
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `vendor` | `string` | the name of the vendor or tool the event belongs to, to namespace the event |
|
||||
| `event` | `string` | the name of the event itself |
|
||||
| `vendor` | `string` | 事件所属的供应商或工具的名称,用于为事件命名 |
|
||||
| `event` | `string` | 事件本身的名称 |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
``null``
|
||||
|
||||
@@ -527,16 +520,16 @@ Add a custom-named event to the Appium event log
|
||||
|
||||
`POST` **`/session/:sessionId/appium/app/reset`**
|
||||
|
||||
Reset the current session (run the delete session and create session subroutines)
|
||||
重置当前会话(运行删除会话并创建会话子程序)
|
||||
|
||||
!!! warning "Deprecated"
|
||||
!!! warning "已弃用"
|
||||
|
||||
Please use each driver's launch, activate, terminate or cleanup method.
|
||||
请使用每个驱动程序的启动、激活、终止或清理方法。
|
||||
|
||||
Use explicit session management commands instead
|
||||
改用显式会话管理命令代替
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
``null``
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
# Plugin: execute-driver
|
||||
# 插件: execute-driver
|
||||
|
||||
### `executeDriverScript`
|
||||
|
||||
`POST` **`/session/:sessionId/appium/execute_driver`**
|
||||
|
||||
Implementation of a command within a plugin
|
||||
在插件中执行命令
|
||||
|
||||
At minimum, `D` must be `ExternalDriver`, but a plugin can be more narrow about which drivers it supports.
|
||||
至少,`D`必须是`ExternalDriver`,但插件可以更严格地限制它支持哪些驱动程序。
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type |
|
||||
| 名字 | 类型 |
|
||||
| :------ | :------ |
|
||||
| `script` | [script: string, scriptType: string, timeoutMs: number] |
|
||||
| `type?` | [script: string, scriptType: string, timeoutMs: number] |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`unknown`
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
# Plugin: images
|
||||
# 插件: images
|
||||
|
||||
### `compareImages`
|
||||
|
||||
`POST` **`/session/:sessionId/appium/compare_images`**
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type |
|
||||
| 名字 | 类型 |
|
||||
| :------ | :------ |
|
||||
| `mode` | `any`[] |
|
||||
| `options?` | `any`[] |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`ComparisonResult`
|
||||
|
||||
@@ -19,49 +19,48 @@
|
||||
|
||||
`POST` **`/session/:sessionId/element`**
|
||||
|
||||
Find a UI element given a locator strategy and a selector, erroring if it can't be found
|
||||
在给定定位策略和选择器的情况下查找UI元素,如果找不到则报错
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-element](https://w3c.github.io/webdriver/#find-element)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `any` | the locator strategy |
|
||||
| `value` | `any` | the selector to combine with the strategy to find the specific element |
|
||||
| `using` | `any` | 定位策略 |
|
||||
| `value` | `any` | 选择器与策略相结合,找到特定元素 |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`any`
|
||||
|
||||
The element object encoding the element id which can be used in element-related
|
||||
commands
|
||||
对元素id进行编码的元素对象,可用于元素相关命令
|
||||
|
||||
### `findElements`
|
||||
|
||||
`POST` **`/session/:sessionId/elements`**
|
||||
|
||||
Find a a list of all UI elements matching a given a locator strategy and a selector
|
||||
查找与给定定位策略和选择器匹配的所有UI元素的列表
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-elements](https://w3c.github.io/webdriver/#find-elements)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `any` | the locator strategy |
|
||||
| `value` | `any` | the selector to combine with the strategy to find the specific elements |
|
||||
| `using` | `any` | 定位策略 |
|
||||
| `value` | `any` | 选择器与策略相结合,找到特定元素s |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`any`
|
||||
|
||||
A possibly-empty list of element objects
|
||||
可能为空的元素对象列表
|
||||
|
||||
@@ -2,23 +2,21 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Intro to Commands
|
||||
title: 命令简介
|
||||
---
|
||||
|
||||
Here you can find various commands exposed by the main Appium module through its base driver, as
|
||||
well as the commands available in several plugins.
|
||||
在这里,您可以找到Appium主模块通过其基本驱动程序公开的各种命令,以及几个插件中可用的命令。
|
||||
|
||||
!!! note
|
||||
!!! 注意
|
||||
|
||||
The Appium base driver only exposes a few commands, as it is not meant to be used on its own.
|
||||
Please refer to the documentation of your [Appium driver](../ecosystem/drivers.md) to learn
|
||||
about the commands it exposes, and then check your [Appium client](../ecosystem/clients.md)
|
||||
documentation for the exact syntax of that command.
|
||||
Appium基本驱动程序只公开少数几个命令,因为它本身不是为单独使用而设计的。
|
||||
请参阅您的[Appium驱动程序](../ecosystem/drivers.md)的文档,了解它公开的命令
|
||||
然后查阅您的[Appium客户端](../ecosystem/clients.md)文档,了解该命令的确切语法。
|
||||
|
||||
命令列表可以在此处找到:
|
||||
|
||||
The command listings can be found here:
|
||||
|
||||
* [Base Driver](./base-driver.md)
|
||||
* [Execute Driver Plugin](./execute-driver-plugin.md)
|
||||
* [Images Plugin](./images-plugin.md)
|
||||
* [Relaxed Caps Plugin](./relaxed-caps-plugin.md)
|
||||
* [Universal XML Plugin](./universal-xml-plugin.md)
|
||||
* [基础驱动程序](./base-driver.md)
|
||||
* [执行驱动程序插件](./execute-driver-plugin.md)
|
||||
* [图片插件](./images-plugin.md)
|
||||
* [宽松能力插件](./relaxed-caps-plugin.md)
|
||||
* [通用XML插件](./universal-xml-plugin.md)
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
# Plugin: relaxed-caps
|
||||
# 插件: relaxed-caps
|
||||
|
||||
### `createSession`
|
||||
|
||||
`POST` **`/session`**
|
||||
|
||||
Start a new automation session
|
||||
开始新的自动化会话
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#new-session](https://w3c.github.io/webdriver/#new-session)
|
||||
|
||||
<!-- comment source: multiple -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `desiredCapabilities?` | `any` | the new session capabilities |
|
||||
| `requiredCapabilities?` | `any` | another place the new session capabilities could be sent (typically left undefined) |
|
||||
| `capabilities?` | `any` | another place the new session capabilities could be sent (typically left undefined) |
|
||||
| `desiredCapabilities?` | `any` | 新的会话功能 |
|
||||
| `requiredCapabilities?` | `any` | 另一个可以发送新会话功能的地方(通常未定义) |
|
||||
| `capabilities?` | `any` | 另一个可以发送新会话功能的地方(通常未定义) |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`any`
|
||||
|
||||
The capabilities object representing the created session
|
||||
所创建会话的能力对象
|
||||
|
||||
@@ -1,68 +1,67 @@
|
||||
# Plugin: universal-xml
|
||||
# 插件: universal-xml
|
||||
|
||||
### `findElement`
|
||||
|
||||
`POST` **`/session/:sessionId/element`**
|
||||
|
||||
Find a UI element given a locator strategy and a selector, erroring if it can't be found
|
||||
在给定定位策略和选择器的情况下查找UI元素,如果找不到则报错
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-element](https://w3c.github.io/webdriver/#find-element)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `any`[] | the locator strategy |
|
||||
| `using` | `any`[] | 定位策略 |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`any`
|
||||
|
||||
The element object encoding the element id which can be used in element-related
|
||||
commands
|
||||
对元素id进行编码的元素对象,可用于元素相关命令
|
||||
|
||||
### `findElements`
|
||||
|
||||
`POST` **`/session/:sessionId/elements`**
|
||||
|
||||
Find a a list of all UI elements matching a given a locator strategy and a selector
|
||||
查找与给定定位策略和选择器匹配的所有UI元素的列表
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#find-elements](https://w3c.github.io/webdriver/#find-elements)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Parameters
|
||||
#### 参数
|
||||
|
||||
| Name | Type | Description |
|
||||
| 名字 | 类型 | 描述 |
|
||||
| :------ | :------ | :------ |
|
||||
| `using` | `any`[] | the locator strategy |
|
||||
| `using` | `any`[] | 定位策略 |
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`any`
|
||||
|
||||
A possibly-empty list of element objects
|
||||
可能为空的元素对象列表
|
||||
|
||||
### `getPageSource`
|
||||
|
||||
`GET` **`/session/:sessionId/source`**
|
||||
|
||||
Get the current page/app source as HTML/XML
|
||||
以HTML/XML格式获取当前页面/应用程序源代码
|
||||
|
||||
**`See`**
|
||||
**`请参阅`**
|
||||
|
||||
[https://w3c.github.io/webdriver/#get-page-source](https://w3c.github.io/webdriver/#get-page-source)
|
||||
|
||||
<!-- comment source: method-signature -->
|
||||
|
||||
#### Response
|
||||
#### 响应
|
||||
|
||||
`string`
|
||||
|
||||
The UI hierarchy in a platform-appropriate format (e.g., HTML for a web page)
|
||||
以适合平台的格式呈现的用户界面层次结构(例如,对于网页使用HTML)
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
---
|
||||
title: Appium's Config System
|
||||
title: Appium的配置系统
|
||||
---
|
||||
|
||||
Appium 2 supports [configuration files](../guides/config.md). A configuration file is intended to
|
||||
have (nearly) 1:1 parity with command-line arguments. An end user can supply Appium 2 with
|
||||
a configuration file, CLI args, or both (the args have precedence over the config file).
|
||||
Appium2支持[配置文件](../guides/config.md)。配置文件是与命令行参数保持(几乎)一一对应的关系。
|
||||
用户可以为Appium2提供配置文件、命令行参数,或者两者都提供(此时命令行参数的优先级高于配置文件)。
|
||||
|
||||
This document will be a technical overview of how the configuration system works. It is intended
|
||||
for Appium contributors, but will also explain the system's fundamental features.
|
||||
本文档将对配置系统的工作原理进行技术概述。它旨在为Appium的贡献者提供指导,但同时也会解释该系统的基础功能。
|
||||
|
||||
## Reading a Config File
|
||||
## 读取配置文件
|
||||
|
||||
A config file is a JSON, JavaScript, or YAML file which can be validated against a schema. By
|
||||
default, this file will be named `.appiumrc.{json,js,yaml,yml}` and should be in the root of the
|
||||
project which depends upon `appium`. Other filenames and locations are supported via the `--config
|
||||
<file>` flag. For obvious reasons, the `config` argument is disallowed within config files.
|
||||
配置文件是一个JSON、JavaScript或YAML文件,可以根据架构进行验证。
|
||||
默认情况下,此文件将被命名为`.appiumrc.{json,js,yaml,yml}`,并位于依赖`appium`的项目的根目录中。
|
||||
通过`--config <file>`标志,还支持其他文件名和位置。出于显而易见的原因,不允许在配置文件中使用`config`参数。
|
||||
|
||||
In lieu of a separate file, configuration can be embedded in a project's `package.json` using the
|
||||
`appiumConfig` property, e.g.,:
|
||||
除了单独的文件外,配置还可以嵌入到项目的`package.json`文件中,使用`appiumConfig`属性。例如:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -29,196 +25,160 @@ In lieu of a separate file, configuration can be embedded in a project's `packag
|
||||
}
|
||||
```
|
||||
|
||||
When an Appium server is started via the `appium` executable, the `init` function in `lib/main.js`
|
||||
will call into `lib/config-file.js` to load and/or search for a configuration file and in
|
||||
`package.json`.
|
||||
当通过`appium`可执行文件启动Appium服务器时,`lib/main.js`中的`init`函数将调用`lib/config-file.js`加载或搜索配置文件和`package.json`。
|
||||
|
||||
!!! note
|
||||
!!! 注意
|
||||
|
||||
It is not an error if configuration isn't found!
|
||||
如果未找到配置文件,这并不会导致错误!
|
||||
|
||||
The [`lilconfig`](https://npm.im/lilconfig) package provides the search & load functionality; refer
|
||||
to its documentation for more information about the search paths. Additionally, Appium provides
|
||||
support for config files written in YAML via the package [`yaml`](https://npm.im/yaml).
|
||||
[`lilconfig`](https://npm.im/lilconfig)包提供了搜索和加载配置文件的功能;有关搜索路径的更多信息,请参考其文档。
|
||||
此外,Appium通过[`yaml`](https://npm.im/yaml)包支持编写YAML格式的配置文件。
|
||||
|
||||
If a config file is found and successfully [validated](#validation), the result will be merged with
|
||||
a set of defaults and any additionall CLI arguments. CLI arguments have precedence over config
|
||||
files, and config files have precedence over defaults.
|
||||
当找到并成功[验证](#_2)配置文件后,其结果将与默认设置以及额外的命令行参数进行合并。
|
||||
在这个合并过程中,命令行参数的优先级高于配置文件,而配置文件的优先级则高于默认设置。
|
||||
|
||||
## Validation
|
||||
## 验证
|
||||
|
||||
The same system is used for _both_ validation of config files _and_ command-line arguments.
|
||||
该系统同时用于配置文件和命令行参数的验证。
|
||||
|
||||
The package [`ajv`](https://npm.im/ajv) provides validation. Of course, to make `ajv` validate
|
||||
anything, it must be provided a _schema_.
|
||||
[ajv](https://npm.im/ajv)包提供了验证功能。当然,为了让`ajv`进行验证,必须为其提供一个模式。
|
||||
|
||||
The _base_ schema is a [JSON Schema
|
||||
Draft-7](https://json-schema.org/draft/2020-12/json-schema-core.html)-compliant object exported by
|
||||
`lib/schema/appium-config-schema.js`. This schema defines configuration _native to Appium_, and
|
||||
only concerns its behavior as a _server_; it does not define configuration for any other
|
||||
functionality (e.g., the `plugin` or `driver` subcommands).
|
||||
基础模式是一个符合[JSON Schema Draft-7](https://json-schema.org/draft/2020-12/json-schema-core.html)标准的对象,
|
||||
由`lib/schema/appium-config-schema.js`文件导出。这个模式定义了Appium原生的配置,并且仅关注其作为服务器的行为;它并没有定义任何其他功能(例如插件或驱动程序子命令)的配置。
|
||||
|
||||
!!! warning
|
||||
!!! 警告
|
||||
|
||||
Note that this file is the _base_ schema; this will become painfully relevant.
|
||||
请注意,这个文件是基础模式文件;这一点在后续操作中会变得至关重要。
|
||||
|
||||
This file is is _not_ a JSON file, because a) JSON is painful to work with for humans, b) is
|
||||
especially reviled by @jlipps, and c) `ajv` accepts objects, not JSON files.
|
||||
此文件不是JSON文件,因为(1)JSON对人类来说很难使用,(2)@jlipps特别讨厌它,(3)`ajv`接受对象,而不是JSON文件。
|
||||
|
||||
It is more straightforward to explain how config files are validated, so we'll start there.
|
||||
解释配置文件是如何被验证的会更加直接明了,所以我们从这里开始。
|
||||
|
||||
### Validating Config Files
|
||||
### 验证配置文件
|
||||
|
||||
When a config file is found (`lib/config-file.js`), it will call the `validate` function exported
|
||||
from `lib/schema/schema.js` with the contents of the config file. In turn, this asks `ajv` to
|
||||
validate the data against the schema that Appium has provided it.
|
||||
当发现一个配置文件(`lib/config-file.js`),它会调用从`lib/schema/schema.js`导出的`validate`函数,并将配置文件的内容作为参数传递给该函数。
|
||||
接着,validate函数会请求`ajv`根据Appium提供的模式来验证这些数据。
|
||||
|
||||
If the config file is invalid, errors will be generated to be displayed to the user. Finally, the
|
||||
`init` function will detect these errors, display them, and the process will exit.
|
||||
如果配置文件无效,ajv会生成错误,这些错误随后会被显示给用户。最后,`init`函数会检测到这些错误,将它们显示出来,并且整个进程会退出。
|
||||
|
||||
I hope that made sense, because this is the easy part.
|
||||
我希望已经解释清楚了,因为这部分相对来说是比较容易理解的。
|
||||
|
||||
### Validating CLI Arguments
|
||||
### 验证CLI参数
|
||||
|
||||
As mentioned earlier, the same system is used for validating both config files and CLI arguments.
|
||||
正如之前提到的,相同的系统被用于验证配置文件和命令行参数。
|
||||
|
||||
Totally not judging, but Appium uses [`argparse`](https://npm.im/argparse) for its CLI argument
|
||||
parsing. This package, and others like it, provides an API to define the arguments a command-line
|
||||
Node.js script accepts, and will ultimately return an object representation of the user-supplied
|
||||
arguments.
|
||||
这里并没有任何评判的意思,但Appium使用[`argparse`](https://npm.im/argparse)来解析命令行参数。
|
||||
这个包以及其他类似的包提供了一个API,用于定义命令行Node.js脚本接受的参数,并最终返回一个表示用户提供的参数的对象。
|
||||
|
||||
Just as the schema defines what's allowed in a config file, it also defines what's allowed on the
|
||||
command-line.
|
||||
就像模式定义了配置文件中允许的内容一样,它也定义了命令行上允许的内容。
|
||||
|
||||
#### Defining CLI Arguments via Schema
|
||||
#### 通过模式定义CLI参数
|
||||
|
||||
CLI arguments must be _defined_ before their values can be validated.
|
||||
在验证命令行参数的值之前,必须先定义这些参数。
|
||||
|
||||
A JSON schema isn't a natural fit for defining CLI args--it needs some grease to make it work--but
|
||||
it's close enough that we can do so with an adapter and some custom metadata.
|
||||
JSON模式并不是定义CLI参数的天然选择,它需要一些额外的处理才能使其适用,
|
||||
但它已经足够接近,以至于我们可以通过一个适配器和一些自定义元数据来实现这一点。
|
||||
|
||||
In `lib/cli/parser.js`, there's a wrapper around `argparse`'s `ArgumentParser`; it's called (wait
|
||||
for it)... `ArgParser`. The wrapper exists because we're doing some custom things with `argparse`,
|
||||
but is has nothing to do with the schema directly.
|
||||
在`lib/cli/parser.js`中,有一个围绕`argparse`库的`ArgumentParser`的包装器;它被称为`ArgParser`。
|
||||
这个包装器存在是因为我们对`argparse`做了一些自定义处理,但它与模式本身没有直接关系。
|
||||
|
||||
An `ArgParser` instance is created and its `parseArgs()` method is called with the raw CLI
|
||||
arguments. The definition of the accepted arguments comes from `lib/cli/args.js` in part--here, all
|
||||
of the arguments _not_ intended for use with the `server` subcommand are hard-coded (e.g., the
|
||||
`driver` subcommand and _its_ subcommands). `args.js` also contains a function `getServerArgs()`,
|
||||
which in turn calls into `toParserArgs` in `lib/schema/cli-args.js`. `lib/schema/cli-args.js` can
|
||||
be considered the "adapter" layer between `argparse` and the schema.
|
||||
创建一个`ArgParser`实例,并用原始的CLI参数调用了它的`parseArgs()`方法,在`lib/cli/args.js`里定义了可以接受的参数。
|
||||
在这里,所有不打算与`server`子命令一起使用的参数都是硬编码的(例如,`driver`子命令及其子命令)。
|
||||
`args.js`还包含一个`getServerArgs()`函数,该函数转而调用`lib/schema/cli-args.js`中的`toParserArgs`。
|
||||
`lib/schema/cli-args.js`可以视为`argparse`和模式之间的“适配器”层。
|
||||
|
||||
`toParserArgs` uses the `flattenSchema` function exported by `lib/schema/schema.js`, which
|
||||
"squashes" the schema into a key/value representation. Then, `toParserArgs` iterates over each
|
||||
key/value pair and "converts" it into a suitable `ArgumentOption` object for final handoff to
|
||||
`ArgParser`.
|
||||
`toParserArgs`使用了由`lib/schema/schema.js`导出的`flattenSchema`函数,该函数将模式“压平”为键值对表示。
|
||||
然后,`toParserArgs`遍历每个键值对,并将其“转换”为适合最终传递给`ArgParser`的`ArgumentOption`对象。
|
||||
|
||||
This adapter (`cli-args.js`) is where most of the mess is hidden; let's explore this rat's nest
|
||||
a bit further.
|
||||
这个适配器(`cli-args.js`)是隐藏大部分混乱的地方;让我们进一步探索这个错综复杂的环境。
|
||||
|
||||
##### CLI & Schema Incongruities
|
||||
##### CLI和模式不一致
|
||||
|
||||
The conversion algorithm (see function `subSchemaToArgDef` in `lib/schema/cli-args.js`) is mostly
|
||||
just hacks and special cases neatly packed into a function. Things that don't cleanly map from
|
||||
`argparse` to a JSON schema include, but are not limited to:
|
||||
转换算法(见`lib/schema/cli-args.js`中的`subSchemaToArgDef`函数)
|
||||
主要就是将各种技巧和特殊情况巧妙地打包到一个函数中。
|
||||
有些事情不能从`argparse`清晰地映射到JSON模式,包括但不限于:
|
||||
|
||||
- A schema cannot natively express "store the value of `--foo=<value>` in a property called `bar`" in a schema (this corresponds to the `ArgumentOption['dest']` prop).
|
||||
- A schema cannot natively express aliases; e.g., `--verbose` can also be `-v`
|
||||
- A schema `enum` is not restricted to multiple types, but `argparse`'s equivalent `ArgumentOption['choices']` prop _is_
|
||||
- A schema does not know about `argparse`'s concept of "actions" (note that Appium is not currently using custom actions--though it did, and it could again).
|
||||
- `argparse` has no native type for `email`, `hostname`, `ipv4`, `uri` etc., and the schema does
|
||||
- Schema validation only _validates_, it does not perform translation, transformation, or coercion (mostly). `argparse` allows this.
|
||||
- Schemas allow the `null` type, for whatever reason. Ever pass `null` on the CLI?
|
||||
- `argparse` does not understand anything other than primitives; no objects, arrays, etc., and certainly not arrays of a particular type.
|
||||
- 模式不能原生的表达“将`--foo=<value>`的值存储在一个名为`bar`的属性中”(这对应于`ArgumentOption['dest']`属性)。
|
||||
- 模式不能原生的表达别名,例如`--verbose`也可以是`-v`。
|
||||
- 模式的枚举不限制于多种类型,但`argparse`中对应的`ArgumentOption['choices']`属性是限制的。
|
||||
- 模式不知道`argparse`中的"动作"概念(注意Appium目前没有使用自定义动作——尽管它曾经使用过,并且可能再次使用)。
|
||||
- `argparse`没有原生的`email`、`hostname`、`ipv4`、`uri`等类型,而模式有。
|
||||
- 模式验证只进行验证,不执行翻译、转换或强制转换(大部分情况下),`argparse`允许这样做。
|
||||
- 出于某种原因模式允许`null`类型,你曾在命令行上传递过`null`吗?
|
||||
- `argparse`除了基本类型之外,不理解其他任何内容,不理解对象、数组等,当然也不理解特定类型的数组。
|
||||
-
|
||||
上述所有情况以及其他情况均由适配器处理。
|
||||
|
||||
All of the above cases and others are handled by the adapter.
|
||||
!!! 警告
|
||||
|
||||
!!! warning
|
||||
适配器中的一些决策是通过抛硬币决定的。如果你好奇为什么某些事情会是这样,那很可能是因为它不得不这样做。
|
||||
|
||||
Some decisions made in the adapter were arrived at via coin toss. If you are curious about why
|
||||
something is the way it is, it's likely that it had to do _something_.
|
||||
让我们更仔细地看看类型的处理。
|
||||
|
||||
Let's look more closely at handling types.
|
||||
#### 通过`ajv`处理参数类型
|
||||
|
||||
#### Argument Types via `ajv`
|
||||
虽然`argparse`允许使用者通过API定义各种参数的类型(例如,字符串、数字、布尔标志等),
|
||||
但Appium大多避免使用这些内置类型。为什么会这样呢?原因如下:
|
||||
|
||||
While `argparse` allows consumers, via its API, to define the _type_ of various arguments (e.g.,
|
||||
a string, number, boolean flag, etc.), Appium mostly avoids these built-in types. _Why is that?_
|
||||
Well:
|
||||
1. 我们已经知道参数的类型,因为我们在模式中已经定义了它。
|
||||
2. `ajv`提供了针对模式的验证。
|
||||
3. 模式允许对类型、允许的值等进行更丰富的表达,这些是`argparse`原生无法提供的。
|
||||
4. 模式的表达能力允许提供更好的错误消息。
|
||||
|
||||
1. We already know the type of an argument, because we've defined it in a schema.
|
||||
2. `ajv` provides validation against a schema.
|
||||
3. A schema allows for greater expression of types, allowed values, etc., than `argparse` can provide natively.
|
||||
4. The expressiveness of a schema allows for better error messaging.
|
||||
因此,适配器避开了`argparse`的内置类型(参见`ArgumentOption['type']`允许的字符串值),
|
||||
而是滥用将函数作为类型提供的能力。例外情况是布尔标志,它们没有`type`,而是有`action: 'store_true'`。
|
||||
至于为什么会这样,可能永远没人知道。
|
||||
|
||||
To that end, the adapter eschews `argparse`'s built-in types (see allowed string values of
|
||||
`ArgumentOption['type']`) and instead abuses the ability to provide a _function_ as a `type`. The
|
||||
exception is _boolean_ flags, which do not have a `type`, but rather `action: 'store_true'`. The
|
||||
world may never know why.
|
||||
##### 类型作为函数
|
||||
|
||||
##### Types as Functions
|
||||
当`type`是一个函数时,这个函数同时执行验证和强制转换(如果需要)。那么这些函数是什么呢?
|
||||
|
||||
When a `type` is a function, the function performs both validation _and_ coercion (if necessary).
|
||||
So what are these functions?
|
||||
> 注意:如果属性类型是布尔值,那么`ArgumentOption`中的`type`会被省略(因此不是一个函数),
|
||||
> 但会提供了一个`action`属性,值为`store_true`。是的,这很奇怪。我不知道为什么。
|
||||
|
||||
> Note: `type` is _omitted_ (and thus _not_ a function) from the `ArgumentOption` if the property
|
||||
> type is `boolean`, and is instead provided an `action` property of `store_true`. Yes, this is
|
||||
> weird. No, I don't know why.
|
||||
这取决于模式。但一般来说,我们会创建一个函数管道,每个函数都对应于模式中的一个关键字。
|
||||
让我们以`port`参数为例,与其询问操作系统Appium运行的用户可以绑定到哪些端口,
|
||||
不如预期这个参数是一个介于1和65535之间的整数。
|
||||
这实际上是由两个函数组成的管道,我们将它们组合在一起:
|
||||
|
||||
Well... it depends upon the schema. But generally speaking, we create a _pipeline_ of functions,
|
||||
each corresponding to a keyword in the schema. Let's take the example of the `port` argument. In
|
||||
lieu of asking the OS which ports the `appium`-running user can bind to, this argument is expected
|
||||
to be an integer between 1 and 65535. This turns out to be two functions which we combine into
|
||||
a pipeline:
|
||||
1. 如果可能,将值转换为整数。因为`process.argv`中的每个值都是字符串,所以如果我们想要一个数字,就必须进行转换。
|
||||
2. 使用`ajv`根据端口的模式验证整数。模式允许我们通过`minimum`和`maximum`关键字定义范围。有关其工作原理的更多信息,请查阅相关文档。
|
||||
|
||||
1. Convert the value to an integer, if possible. Because _every value in `process.argv` is a string_, we must coerce if we want a number.
|
||||
2. Use `ajv` to validate the integer against the schema for `port`. A schema lets us define a range via the `minimum` and `maximum` keywords. Read more about how this works in
|
||||
就像配置文件验证一样,如果检测到错误,Appium会友好地告诉用户,并附带一些帮助文本然后退出进程。
|
||||
|
||||
Much like the config file validation, if errors are detected, Appium nicely tells the end-user and
|
||||
the process exits w/ some help text.
|
||||
对于其他本身就是非基本类型的参数,事情就没那么简单了。
|
||||
|
||||
For other arguments which are naturally of non-primitive types, things are not so straightforward.
|
||||
##### 转换器
|
||||
|
||||
##### Transformers
|
||||
还记得`argparse`无法理解数组吗?但如果表达一个值最直观的方式实际上是一个数组怎么办?
|
||||
|
||||
Remember how `argparse` doesn't understand arrays? What if the most ergonomic way to express
|
||||
a value is, in fact, an array?
|
||||
虽然Appium可以在配置文件中接受数组,但在命令行界面上却不能。
|
||||
Appium可以接受一个逗号分隔的字符串(CSV行),或者是一个字符串文件路径,
|
||||
指向包含分隔列表的文件。无论哪种方式,当值从参数解析器中输出时,它都应该是一个数组。
|
||||
|
||||
Well, Appium can't accept an array on the CLI, even though it can accept one in the config file.
|
||||
But Appium _can_ accept a comma-delimited string (a CSV "line"). Or a string filepath referring to
|
||||
a file which _contains_ a delimited list. Either way: by the time the value gets out of the
|
||||
argument parser, it should be an array.
|
||||
如上所述,JSON模式的原生功能无法表达这一点。然而可以定义一个自定义关键字,
|
||||
Appium可以检测并相应地处理它,这就是Appium所做的。
|
||||
|
||||
And as mentioned above, the native facilities of a JSON schema cannot express this. However, it's
|
||||
possible to define a _custom keyword_ which Appium can then detect and handle accordingly. So
|
||||
that's what Appium does.
|
||||
在这种情况下,使用`ajv`注册了一个自定义关键字`appiumCliTransformer`。
|
||||
在编写本文时,`appiumCliTransformer`的值可以是`csv`或`json`。
|
||||
在基础模式文件`appium-config-schema.js`中,如果希望这种行为发生,
|
||||
Appium会使用`appiumCliTransformer: 'csv'`。
|
||||
|
||||
In this case, a custom keyword `appiumCliTransformer` is registered with `ajv`. The value of
|
||||
`appiumCliTransformer` (at the time of this writing) can be `csv` or `json`. In the base schema
|
||||
file, `appium-config-schema.js`, Appium uses `appiumCliTransformer: 'csv'` if this behavior is
|
||||
desired.
|
||||
!!! 注意
|
||||
|
||||
!!! note
|
||||
在模式中定义的任何类型为数组的属性都会自动使用csv转换器。同样,类型为对象的属性将使用json转换器。
|
||||
可以想象,某些情况下数组可能想要使用JSON转换器,但除此之外,
|
||||
在类型为数组或对象的属性上使用`appiumCliTransformer`关键字并不是严格必要的。
|
||||
|
||||
适配器(还记得适配器吗?)创建了一个管道函数,其中包括一个特殊的“CSV转换器”,转换器在`lib/schema/cli-transwers.js`中定义,
|
||||
并将此函数作为值传递给`argparse`的`ArgumentOption`的`type`属性,在这种情况下,模式中的`type: 'array'`将被忽略。
|
||||
|
||||
Any property defined in the schema having type `array` will _automatically_ uses the `csv`
|
||||
transformer. Likewise, a property having type `object` will use the `json` transformer. It's
|
||||
conceivable that `array` may want to use the `json` transformer, but otherwise, the presence of
|
||||
the `appiumCliTransformer` keyword on an `array`-or-`object`-typed property is not stricly
|
||||
necessary.
|
||||
!!! 注意
|
||||
|
||||
The adapter (remember the adapter?) creates a pipeline function including a special "CSV
|
||||
transformer" (transformers are defined in `lib/schema/cli-transformers.js`), and uses this function
|
||||
as the `type` property of the `ArgumentOption` passed into `argparse`. In this case, the `type:
|
||||
'array'` in the schema is ignored.
|
||||
配置文件不需要执行任何复杂的值转换,因为它自然允许Appium准确定义它所期望的内容。
|
||||
因此Appium不会对配置文件值进行后期处理。
|
||||
|
||||
!!! note
|
||||
|
||||
The config file doesn't _need_ to perform any complex transformation of values, because it
|
||||
naturally allows Appium to define exactly what it expects. So Appium does no post-processing of
|
||||
config file values.
|
||||
|
||||
Properties that do not need this special treatment use `ajv` directly for validation. How this
|
||||
works requires some explanation, so that's next.
|
||||
不需要这种特殊处理的属性直接使用`ajv`进行验证。这是如何工作的一些解释,所以接下来就是这样。
|
||||
|
||||
#### Validation of Individual Arguments via `ajv`
|
||||
|
||||
@@ -226,7 +186,7 @@ When we think of a JSON schema, we tend to think, "I have this JSON file and I w
|
||||
against the schema". That's valid, and in fact Appium does just that with config files! However,
|
||||
Appium does not do this when validating arguments.
|
||||
|
||||
!!! note
|
||||
!!! 注意
|
||||
|
||||
During implementation, I was tempted to mash all of the arguments together into
|
||||
a config-file-like data structure and then validate it all at once. I think that would have
|
||||
@@ -277,7 +237,7 @@ about this `my-schema.json`, then we can call its `getSchema(ref)` method (which
|
||||
property, but is a misnomer nonetheless) to get a validation function; `validate(value, ref)` in
|
||||
`schema.js` calls this validation function.
|
||||
|
||||
!!! note
|
||||
!!! 注意
|
||||
|
||||
The schema spec says a schema author can supply an explicit `$id` keyword to override this;
|
||||
it's unsupported by Appium at this time. If needed, extension authors must carefully use `$ref`
|
||||
@@ -358,7 +318,7 @@ The corresponding property in a config file would be
|
||||
The naming convention described above avoids problems of one extension type having a name conflict
|
||||
with a different extension type.
|
||||
|
||||
!!! note
|
||||
!!! 注意
|
||||
|
||||
While an extension can provide aliases via `appiumCliAliases`, "short" flags are disallowed,
|
||||
since all arguments from extensions are prefixed with `--<extension-type>-<extension-name>-`.
|
||||
@@ -412,7 +372,7 @@ extension schemas are kept separately, but the _references_ are added to the sch
|
||||
ultimately added to `ajv`. This works because an `Ajv` instance understands references _from_ any
|
||||
schema it knows about _to_ any schema it knows about.
|
||||
|
||||
!!! note
|
||||
!!! 注意
|
||||
|
||||
This makes it impossible to provide a complete static schema for Appium _and_ the installed
|
||||
extensions (as of Nov 5 2021). A static `.json` schema _is_ generated from the base (via a Gulp
|
||||
|
||||
@@ -1,89 +1,89 @@
|
||||
---
|
||||
title: Contributing Code
|
||||
title: 贡献代码
|
||||
---
|
||||
|
||||
To contribute to the Appium code base make sure to check out the Git repository.
|
||||
要为Appium代码库做出贡献,请务必查看Git存储库。
|
||||
|
||||
!!! info
|
||||
!!! 信息
|
||||
|
||||
If you are VS Code user you can easily check out the project using [Runme](https://runme.dev/api/runme?repository=https%3A%2F%2Fgithub.com%2Fappium%2Fappium.git&fileToOpen=packages%2Fappium%2Fdocs%2Fen%2Fcontributing%2Findex.md).
|
||||
如果您是VS Code用户,您可以使用[Runme](https://runme.dev/api/runme?repository=https%3A%2F%2Fgithub.com%2Fappium%2Fappium.git&fileToOpen=packages%2Fappium%2Fdocs%2Fen%2Fcontributing%2Findex.md)轻松查看项目。
|
||||
|
||||
It is advised to [fork](https://github.com/appium/appium/fork) before cloning it to your system.
|
||||
建议在将其克隆到您的系统之前进行[fork](https://github.com/appium/appium/fork)。
|
||||
|
||||
```sh
|
||||
export GITHUB_USERNAME=<your-username>
|
||||
git clone git@github.com:$GITHUB_USERNAME/appium.git
|
||||
```
|
||||
|
||||
After cloning you can go ahead and install the project dependencies:
|
||||
克隆后,您可以继续安装项目依赖项:
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
From here on there are several things you can do.
|
||||
从现在开始,你可以做几件事。
|
||||
|
||||
### Watch Files
|
||||
### 监视文件
|
||||
|
||||
When developing Appium code we have to watch all JavaScript and TypeScript files to re-compile them after every change. You can run this watch process via:
|
||||
在开发Appium代码时,我们必须查看所有JavaScript和TypeScript文件,以便在每次更改后重新编译它们。您可以通过以下方式运行此监视过程:
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Start Appium in Dev-Mode
|
||||
### 在开发模式下启动Appium
|
||||
|
||||
To test your changes you can run Appium in dev mode via:
|
||||
要测试您的更改,您可以通过以下方式在开发模式下运行Appium:
|
||||
|
||||
```sh
|
||||
npm start
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
### 运行测试
|
||||
|
||||
The project maintains a set of different test variations you can run to verify the quality of the code.
|
||||
该项目维护了一组不同的测试变体,您可以运行这些变体来验证代码的质量。
|
||||
|
||||
#### Linting
|
||||
#### 代码风格检查
|
||||
|
||||
Appium uses [`eslint`](https://eslint.org/) for static code analysis and linting. You can run these checks via:
|
||||
Appium使用[`eslint`](https://eslint.org/)进行静态代码分析和代码风格检查。你可以通过以下方式运行这些检查:
|
||||
|
||||
```sh
|
||||
npm run lint
|
||||
```
|
||||
|
||||
#### Unit
|
||||
#### 单元测试
|
||||
|
||||
```sh
|
||||
npm run test:unit
|
||||
```
|
||||
|
||||
You can also run tests for specific workspaces, e.g.:
|
||||
您还可以对特定工作区运行测试,例如:
|
||||
|
||||
```sh
|
||||
export APPIUM_WORKSPACE=@appium/doctor
|
||||
npm run test:unit -w $APPIUM_WORKSPACE
|
||||
```
|
||||
|
||||
#### Smoke and E2E
|
||||
#### 冒烟和端到端测试
|
||||
|
||||
```sh
|
||||
npm run test:slow
|
||||
```
|
||||
|
||||
### Deploy Docs Locally
|
||||
### 在本地部署文档
|
||||
|
||||
Our documentation system uses [MKDocs](https://www.mkdocs.org/) and therefore requires [Python](https://www.python.org/) to be installed on your system. You can run the docs by:
|
||||
我们的文档系统使用[MKDocs](https://www.mkdocs.org/),因此需要在您的系统上安装[Python](https://www.python.org/)。您可以通过以下方式运行文档:
|
||||
|
||||
```sh
|
||||
# installing needed Python dependencies
|
||||
pip install -r packages/docutils/requirements.txt
|
||||
# build the project
|
||||
# 安装所需的Python依赖项
|
||||
PIP_BREAK_SYSTEM_PACKAGES=1 pip install -r packages/docutils/requirements.txt
|
||||
# 构建项目
|
||||
npm run build
|
||||
# run dev server
|
||||
# 运行开发服务器
|
||||
npm run dev:docs
|
||||
```
|
||||
|
||||
You should be able to view the page at `http://127.0.0.1:8000/docs/en`:
|
||||
您应该可以在`http://127.0.0.1:8000/docs/en`查看页面:
|
||||
|
||||
```sh
|
||||
open http://127.0.0.1:8000/docs/en
|
||||
|
||||
@@ -2,37 +2,31 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Contributing to Appium
|
||||
title: 为Appium做出贡献
|
||||
---
|
||||
|
||||
Appium is open source, available under an Apache 2.0 license. Appium's copyright is held by the
|
||||
[OpenJS Foundation](https://openjsf.org), and Appium receives contributions from many companies
|
||||
across several software industries, regardless of their competitive status. (3rd-party drivers and
|
||||
plugins are available under the licenses provided by their authors.)
|
||||
Appium是一个开源项目,遵循Apache 2.0许可证。其版权由[OpenJS基金会](https://openjsf.org)持有,
|
||||
并且Appium接收来自多个软件行业中的公司的贡献,无论这些公司是否具有竞争关系。
|
||||
(第三方驱动程序和插件在其作者提供的许可证下可用。)
|
||||
|
||||
As such, we welcome contributions! The project moves forward in relation to the investment of
|
||||
contributions of code, documentation, maintenance, and support from companies and volunteers.
|
||||
因此,我们欢迎所有贡献!该项目的进展依赖于来自公司和志愿者的代码、文档、维护和支持的投入。
|
||||
|
||||
This section of Appium's documentation is for those who are interested in contributing to Appium's
|
||||
development. It contains developer overviews, guides, and notes. Use the navigation menu to find
|
||||
a specific topic. All the information in these guides assumes in-depth familiarity with Appium
|
||||
already.
|
||||
Appium文档的这一部分是为那些有兴趣为Appium开发做出贡献的人准备的。它包含了开发者概览、指南和说明。
|
||||
请使用导航菜单来查找特定主题。这些指南中的所有信息都假设您已经对Appium有了深入的了解。
|
||||
|
||||
!!! warning
|
||||
!!! 警告
|
||||
|
||||
Developer information may not be kept up to date as frequently as user-facing information, or
|
||||
it may be most relevant in its current form on the online repository, not in this published
|
||||
version. Always be sure to check the repo or discuss with maintainers. We're always happy to
|
||||
help new contributors get started!
|
||||
开发者信息可能不会像面向用户的信息那样频繁更新,或者其当前形式可能在线仓库中最为相关,而非发布的版本中。
|
||||
请务必检查仓库或与维护者讨论以确保信息的准确性。我们总是乐于帮助新贡献者入门!
|
||||
|
||||
## Ways to Contribute
|
||||
## 贡献方式
|
||||
|
||||
The project offers a variety of ways to contribute, e.g.:
|
||||
该项目提供了多种贡献方式,例如:
|
||||
|
||||
- [contributing code](./develop.md)
|
||||
- improving documentation
|
||||
- creating educational content (blog posts, tutorials, videos, etc.)
|
||||
- spreading the good word about the project (e.g. via Twitter)
|
||||
- filing bugs if you discover them while using Appium
|
||||
- making feature requests if you are missing something in the project or help triaging bugs
|
||||
- supporting users in the [Appium forum](https://discuss.appium.io/)
|
||||
- [贡献代码](./develop.md)
|
||||
- 改进文档
|
||||
- 创建教育内容(博客文章、教程、视频等)
|
||||
- 传播有关该项目的好话(例如通过Twitter)
|
||||
- 如果你在使用Appium的过程中发现了漏洞,请提交它们。
|
||||
- 如果你发现项目中缺少某些功能,或者愿意协助处理漏洞,请提出请求。
|
||||
- 支持[Appium论坛](https://discuss.appium.io/)中的用户
|
||||
|
||||
@@ -2,41 +2,37 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Appium Clients
|
||||
title: Appium客户端
|
||||
---
|
||||
|
||||
You need a client to write and run Appium scripts. You'll want to become very
|
||||
familiar with your client documentation (as well as the documentation of any Selenium client that
|
||||
the Appium client depends on) since that will be your primary interface to Appium.
|
||||
您需要一个客户端来编写和运行Appium脚本。您需要非常熟悉您的客户端文档(以及Appium客户端所依赖的任何Selenium客户端的文档),因为这将是您与Appium的主要接口。
|
||||
|
||||
To learn more about clients, read our [Client Intro](../intro/clients.md).
|
||||
要了解更多关于客户端的信息,请阅读我们的[客户端简介](../intro/clients.md)。
|
||||
|
||||
### Official Clients
|
||||
### 官方客户端
|
||||
|
||||
These clients are currently maintained by the Appium team:
|
||||
这些客户端目前由Appium团队维护:
|
||||
|
||||
|Client|Language|
|
||||
|客户端|编程语言|
|
||||
|-|-|
|
||||
|[Appium Java client](https://github.com/appium/java-client)|Java|
|
||||
|[Appium Python client](https://github.com/appium/python-client)|Python|
|
||||
|[Appium Ruby Core client](https://github.com/appium/ruby_lib_core) (Recommended)<br>[Appium Ruby client](https://github.com/appium/ruby_lib)|Ruby|
|
||||
|[Appium .NET client](https://github.com/appium/dotnet-client)|C#|
|
||||
|
||||
### Other Clients
|
||||
### 其他客户端
|
||||
|
||||
These clients are not maintained by the Appium team and can be used with other languages:
|
||||
这些客户端不由Appium团队维护,可以与其他语言一起使用:
|
||||
|
||||
|Client|Language|
|
||||
|客户端|编程语言|
|
||||
|-|-|
|
||||
|[WebdriverIO](https://webdriver.io/docs/appium)|Node.js|
|
||||
|[Nightwatch.js](https://nightwatchjs.org/guide/mobile-app-testing/introduction.html)|Node.js|
|
||||
|[RobotFramework](https://github.com/serhatbolsu/robotframework-appiumlibrary)|DSL|
|
||||
|[multicatch's appium-client](https://github.com/multicatch/appium-client)|Rust|
|
||||
|
||||
In general, any W3C WebDriver spec-compatible client will also integrate well with Appium, though
|
||||
some Appium-specific commands may not be implemented in other clients.
|
||||
一般来说,任何兼容W3C WebDriver规范的客户端,也可以和Appium很好地集成,尽管某些Appium特定的命令可能无法在其他客户端中实现。
|
||||
|
||||
!!! note
|
||||
!!! 注意
|
||||
|
||||
If you maintain an Appium client that you would like to be listed in the Appium docs, feel free
|
||||
to make a PR to add it to this section with a link to the documentation for the client.
|
||||
如果您维护了一个Appium客户端,并希望在Appium文档中列出,请随时进行PR,将其添加到本部分,并附上客户端文档的链接。
|
||||
|
||||
@@ -2,24 +2,23 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Appium Drivers
|
||||
title: Appium驱动
|
||||
---
|
||||
|
||||
You can't use Appium without at least one driver! Click on the link for each driver to see the
|
||||
specific installation instructions and documentation for that driver.
|
||||
如果没有至少一个驱动程序,您就无法使用Appium!单击每个驱动程序的链接,查看该驱动程序的具体安装说明和文档。
|
||||
|
||||
Generally, drivers can be installed using their listed installation key, with the following command:
|
||||
通常,可以使用下面列出的驱动名称,使用以下命令安装驱动程序:
|
||||
```
|
||||
appium driver install <installation key>
|
||||
appium driver install <驱动名称>
|
||||
```
|
||||
|
||||
To learn more about drivers, check out the [Driver Intro](../intro/drivers.md).
|
||||
要了解有关驱动的更多信息,请查看[驱动简介](../intro/drivers.md)。
|
||||
|
||||
### Official Drivers
|
||||
### 官方驱动
|
||||
|
||||
These drivers are currently maintained by the Appium team:
|
||||
这些驱动程序目前由Appium团队维护:
|
||||
|
||||
|Driver|Installation Key|Platform(s)|Mode(s)|
|
||||
|驱动|驱动名称|支持的平台|支持的形式|
|
||||
|--|--|--|--|
|
||||
|[Chromium](https://github.com/appium/appium-chromium-driver)|`chromium`|macOS, Windows, Linux|Web|
|
||||
|[Espresso](https://github.com/appium/appium-espresso-driver)|`espresso`|Android|Native|
|
||||
@@ -30,11 +29,11 @@ These drivers are currently maintained by the Appium team:
|
||||
|[Windows](https://github.com/appium/appium-windows-driver)|`windows`|Windows|Native|
|
||||
|[XCUITest](https://github.com/appium/appium-xcuitest-driver)|`xcuitest`|iOS|Native, Hybrid, Web|
|
||||
|
||||
### Other Drivers
|
||||
### 其他驱动
|
||||
|
||||
These drivers are not maintained by the Appium team and can be used to target additional platforms:
|
||||
这些驱动程序不由Appium团队维护,可用于针对其他平台:
|
||||
|
||||
|Driver|Installation Key|Platform(s)|Mode(s)|Supported By|
|
||||
|驱动|驱动名称|支持的平台|支持的形式|维护者|
|
||||
|--|--|--|--|--|
|
||||
|[Flutter](https://github.com/appium/appium-flutter-driver)|`--source=npm appium-flutter-driver`|iOS, Android|Native|Community|
|
||||
|[Flutter Integration](https://github.com/AppiumTestDistribution/appium-flutter-integration-driver)|`--source=npm appium-flutter-integration-driver`|iOS, Android|Native|Community / `@AppiumTestDistribution`|
|
||||
@@ -45,7 +44,6 @@ These drivers are not maintained by the Appium team and can be used to target ad
|
||||
|[TizenTV](https://github.com/headspinio/appium-tizen-tv-driver)|`--source=npm appium-tizen-tv-driver`|Samsung TV|Web|HeadSpin|
|
||||
|[Youi](https://github.com/YOU-i-Labs/appium-youiengine-driver)|`--source=npm appium-youiengine-driver`|iOS, Android, macOS, Linux, tvOS|Native|Community / You.i|
|
||||
|
||||
!!! note
|
||||
!!! 注意
|
||||
|
||||
If you maintain an Appium driver that you would like to be listed in the Appium docs, feel free
|
||||
to make a PR to add it to this section with a link to the driver documentation.
|
||||
如果您维护了一个Appium驱动程序,并希望在Appium文档中列出,请随时进行PR,将其添加到本部分,并附上驱动程序文档的链接。
|
||||
|
||||
@@ -2,44 +2,43 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Ecosystem Overview
|
||||
title: 生态系统概述
|
||||
---
|
||||
|
||||
Appium has a wide ecosystem of related software and tools. This section of the Appium documentation
|
||||
aims to compile a listing of various officially-supported and community-supported Appium projects:
|
||||
Appium拥有广泛的相关软件和工具生态系统。文档的这一部分旨在编制各种官方支持和社区支持的Appium项目的列表:
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- :material-car: __Drivers__
|
||||
- :material-car: __驱动__
|
||||
|
||||
---
|
||||
|
||||
Link Appium to your test device
|
||||
将Appium链接到您的测试设备
|
||||
|
||||
[:octicons-arrow-right-24: View all drivers](./drivers.md)
|
||||
[:octicons-arrow-right-24: 查看所有驱动](./drivers.md)
|
||||
|
||||
- :octicons-code-16: __Clients__
|
||||
- :octicons-code-16: __客户端__
|
||||
|
||||
---
|
||||
|
||||
Link Appium to your automation code
|
||||
将Appium链接到您的自动化代码
|
||||
|
||||
[:octicons-arrow-right-24: View all clients](./clients.md)
|
||||
[:octicons-arrow-right-24: 查看所有客户端](./clients.md)
|
||||
|
||||
- :fontawesome-solid-plug: __Plugins__
|
||||
- :fontawesome-solid-plug: __插件__
|
||||
|
||||
---
|
||||
|
||||
Modify and extend Appium functionality
|
||||
修改和扩展Appium功能
|
||||
|
||||
[:octicons-arrow-right-24: View all plugins](./plugins.md)
|
||||
[:octicons-arrow-right-24: 查看所有插件](./plugins.md)
|
||||
|
||||
- :material-wrench: __Tools__
|
||||
- :material-wrench: __工具__
|
||||
|
||||
---
|
||||
|
||||
Interact with Appium in other ways
|
||||
以其他方式与Appium交互
|
||||
|
||||
[:octicons-arrow-right-24: View all tools](./tools.md)
|
||||
[:octicons-arrow-right-24: 查看所有工具](./tools.md)
|
||||
|
||||
</div>
|
||||
@@ -2,44 +2,42 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Appium Plugins
|
||||
title: Appium插件
|
||||
---
|
||||
|
||||
Plugins offer various ways to extend or modify Appium's behaviour. They are _completely optional_
|
||||
and are not needed for standard automation functionality, but you may find them to be useful
|
||||
for more specialised automation workflows.
|
||||
插件提供了各种方法来扩展或修改Appium的行为。它们是完全可选的,不是标准自动化功能所必需的,但您可能会发现它们对更专业的自动化工作流程很有用。
|
||||
|
||||
通常,可以使用下面列出的插件名称,使用以下命令安装插件:
|
||||
|
||||
Generally, plugins can be installed using their listed installation key, with the following command:
|
||||
```
|
||||
appium plugin install <installation key>
|
||||
appium plugin install <插件名称>
|
||||
```
|
||||
|
||||
### Official Plugins
|
||||
### 官方插件
|
||||
|
||||
These plugins are are currently maintained by the Appium team:
|
||||
这些插件目前由Appium团队维护:
|
||||
|
||||
|<div style="width:7em">Plugin</div>|<div style="width:8em">Installation Key</div>|Description|
|
||||
|<div style="width:7em">插件</div>|<div style="width:8em">插件名称</div>|简介|
|
||||
|---|---|---|
|
||||
|[Execute Driver](https://github.com/appium/appium/tree/master/packages/execute-driver-plugin)|`execute-driver`|Run entire batches of commands in a single call to the Appium server|
|
||||
|[Images](https://github.com/appium/appium/tree/master/packages/images-plugin)|`images`|Image matching and comparison features|
|
||||
|[Relaxed Caps](https://github.com/appium/appium/tree/master/packages/relaxed-caps-plugin)|`relaxed-caps`|Relax Appium's requirement for vendor prefixes on capabilities|
|
||||
|[Universal XML](https://github.com/appium/appium/tree/master/packages/universal-xml-plugin)|`universal-xml`|Instead of the standard XML format for iOS and Android, use an XML definition that is the same across both platforms|
|
||||
|[Execute Driver](https://github.com/appium/appium/tree/master/packages/execute-driver-plugin)|`execute-driver`|在对Appium服务器的一次调用中运行整批命令|
|
||||
|[Images](https://github.com/appium/appium/tree/master/packages/images-plugin)|`images`|图像匹配和比较功能|
|
||||
|[Relaxed Caps](https://github.com/appium/appium/tree/master/packages/relaxed-caps-plugin)|`relaxed-caps`|放宽Appium对功能上供应商前置的要求|
|
||||
|[Universal XML](https://github.com/appium/appium/tree/master/packages/universal-xml-plugin)|`universal-xml`|使用在两个平台上都相同的XML定义,而不是iOS和Android的标准XML格式|
|
||||
|
||||
### Other Plugins
|
||||
### 其他插件
|
||||
|
||||
These plugins are not maintained by the Appium team and can provide additional functionality:
|
||||
这些插件不由Appium团队维护,可以提供其他功能:
|
||||
|
||||
|<div style="width:6em">Plugin</div>|<div style="width:19em">Installation Key</div>|Description|<div style="width:13em">Supported By</div>|
|
||||
|<div style="width:6em">插件</div>|<div style="width:19em">插件名称</div>|简介|<div style="width:13em">维护者</div>|
|
||||
|---|---|---|---|
|
||||
|[AltUnity](https://github.com/headspinio/appium-altunity-plugin)|`--source=npm appium-altunity-plugin`|Target Unity games and apps for automation with a new context, via the AltUnityTester framework|HeadSpin|
|
||||
|[Device Farm](https://github.com/AppiumTestDistribution/appium-device-farm)|`--source=npm appium-device-farm`|Manage and create driver sessions on connected Android devices and iOS simulators|`@AppiumTestDistribution`|
|
||||
|[Gestures](https://github.com/AppiumTestDistribution/appium-gestures-plugin)|`--source=npm appium-gestures-plugin`|Perform basic gestures using W3C Actions|`@AppiumTestDistribution`|
|
||||
|[Interceptor](https://github.com/AppiumTestDistribution/appium-interceptor-plugin)|`--source=npm appium-interceptor`|Intercept and mock API requests and responses|`@AppiumTestDistribution`|
|
||||
|[OCR](https://github.com/jlipps/appium-ocr-plugin)|`--source=npm appium-ocr-plugin`|Find elements via OCR text|`@jlipps`|
|
||||
|[Reporter](https://github.com/AppiumTestDistribution/appium-reporter-plugin)|`--source=npm appium-reporter-plugin`|Generate standalone consolidated HTML reports with screenshots|`@AppiumTestDistribution`|
|
||||
|[Wait](https://github.com/AppiumTestDistribution/appium-wait-plugin)|`--source=npm appium-wait-plugin`|Manage global element wait timeouts|`@AppiumTestDistribution`|
|
||||
|[AltUnity](https://github.com/headspinio/appium-altunity-plugin)|`--source=npm appium-altunity-plugin`|通过AltUnityTester框架,为Unity游戏和应用程序提供新的自动化环境|HeadSpin|
|
||||
|[Device Farm](https://github.com/AppiumTestDistribution/appium-device-farm)|`--source=npm appium-device-farm`|在连接的Android设备和iOS模拟器上管理和创建驱动程序会话|`@AppiumTestDistribution`|
|
||||
|[Gestures](https://github.com/AppiumTestDistribution/appium-gestures-plugin)|`--source=npm appium-gestures-plugin`|使用W3C操作执行基本手势|`@AppiumTestDistribution`|
|
||||
|[Interceptor](https://github.com/AppiumTestDistribution/appium-interceptor-plugin)|`--source=npm appium-interceptor`|拦截和模拟API请求和响应|`@AppiumTestDistribution`|
|
||||
|[OCR](https://github.com/jlipps/appium-ocr-plugin)|`--source=npm appium-ocr-plugin`|通过OCR文本查找元素|`@jlipps`|
|
||||
|[Reporter](https://github.com/AppiumTestDistribution/appium-reporter-plugin)|`--source=npm appium-reporter-plugin`|通过屏幕截图生成独立的合并HTML报告|`@AppiumTestDistribution`|
|
||||
|[Wait](https://github.com/AppiumTestDistribution/appium-wait-plugin)|`--source=npm appium-wait-plugin`|管理全局元素等待超时|`@AppiumTestDistribution`|
|
||||
|
||||
!!! note
|
||||
!!! 注意
|
||||
|
||||
If you maintain an Appium plugin that you would like to be listed in the Appium docs, feel free
|
||||
to make a PR to add it to this section with a link to the documentation for the plugin.
|
||||
如果您维护了一个Appium插件,并希望在Appium文档中列出,请随时进行PR,将其添加到本部分,并附上插件文档的链接。
|
||||
|
||||
@@ -2,41 +2,37 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Appium-Related Tools
|
||||
title: Appium相关工具
|
||||
---
|
||||
|
||||
There are several Appium tools that have been created to to assist with things not directly related
|
||||
to testing, such as Appium installation, test development, and more.
|
||||
这里有几个Appium工具来帮助处理与测试没有直接关系的事情,例如Appium安装、测试开发等。
|
||||
|
||||
### [Appium Inspector](https://appium.github.io/appium-inspector/latest/)
|
||||
|
||||
Appium has a graphical client which can be used to inspect application screenshots, view the
|
||||
application hierarchy, run Appium commands, record app interactions, and more. It is very useful
|
||||
for Appium test development.
|
||||
Appium有一个图形客户端,可用于检查应用程序屏幕截图、查看应用程序层次结构、运行Appium命令、记录应用程序交互等。它对Appium测试开发非常有用。
|
||||
|
||||
Find downloads and more information on its GitHub page: [Appium Inspector](https://github.com/appium/appium-inspector)
|
||||
在其GitHub页面上查找下载和更多信息:[Appium Inspector](https://github.com/appium/appium-inspector)
|
||||
|
||||
### Appium Doctor
|
||||
|
||||
Appium Doctor is a command-line tool built into Appium drivers and plugins.
|
||||
The command is expected to be used to validate whether a driver or plugin has all of its prerequisites and other environment details set up correctly
|
||||
if the driver/plugin author implemented the `doctor` command.
|
||||
Appium Doctor是一个内置于Appium驱动程序和插件中的命令行工具。如果驱动程序/插件作者实现了`doctor`命令,
|
||||
则该命令将用于验证驱动程序或插件是否正确设置了所有先决条件和其他环境详细信息。
|
||||
|
||||
For example, `uiautomator2` driver provides the `doctor` command below.
|
||||
例如,`uiautomator2`驱动程序提供以下`doctor`命令。
|
||||
|
||||
```
|
||||
appium driver doctor uiautomator2
|
||||
```
|
||||
|
||||
It shows no result if the driver/plugin author did not implement them.
|
||||
如果驱动程序/插件作者没有实现它们,则不会显示任何结果。
|
||||
|
||||
More information on this command can be found in the [Command-Line Usage documentation](../cli/extensions.md#doctor).
|
||||
For driver/plugin developers, please read [Building Doctor Checks](../developing/build-doctor-checks.md).
|
||||
有关此命令的更多信息,请参阅[命令行使用文档](../cli/extensions.md#doctor)。
|
||||
对于驱动程序/插件开发人员,请阅读[构建医生检查](../developing/build-doctor-checks.md)。
|
||||
|
||||
### Other Tools
|
||||
### 其他工具
|
||||
|
||||
These tools are not maintained by the Appium team and can be used to assist with other problems:
|
||||
这些工具不由Appium团队维护,可以用于协助解决其他问题:
|
||||
|
||||
|Name|Description|Supported By|
|
||||
|名字|简介|维护者|
|
||||
|---|---|---|
|
||||
|[appium-installer](https://github.com/AppiumTestDistribution/appium-installer)|Help set up an Appium environment for Android and iOS|`@AppiumTestDistribution`|
|
||||
|[appium-installer](https://github.com/AppiumTestDistribution/appium-installer)|为Android和iOS设置Appium环境|`@AppiumTestDistribution`|
|
||||
|
||||
@@ -14,7 +14,7 @@ environment before it is merged or published. This tutorial describes how to ach
|
||||
|
||||
## Installation
|
||||
|
||||
- [Check out]((https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally)) the PR locally.
|
||||
- [Check out](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally) the PR locally.
|
||||
There is also an option (although it is less flexible, because you won't be able to easily fetch
|
||||
any changes to this PR later) to simply [download](https://docs.github.com/en/repositories/working-with-files/using-files/downloading-source-code-archives) and unzip the sources
|
||||
locally. If you choose the later option then no `git` tool would be necessary.
|
||||
|
||||
@@ -22,11 +22,6 @@ title: 欢迎
|
||||
Appium非常感谢主要合作伙伴的支持!(了解更多关于我们的赞助计划和贡献者补偿计划信息请<a
|
||||
href="https://github.com/appium/appium/blob/master/GOVERNANCE.md#sponsorship">点击此处</a>)
|
||||
<div class="homepageSponsors">
|
||||
<div class="homepageSponsor">
|
||||
<a href="https://www.headspin.io/solutions/appium-mobile-test-automation">
|
||||
<img src="assets/images/sponsor-logo-headspin.png" style="width: 200px;" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="homepageSponsor">
|
||||
<a href="https://www.browserstack.com/browserstack-appium?utm_campaigncode=701OW00000AoUTQYA3&utm_medium=partnered&utm_source=appium">
|
||||
<img src="assets/images/sponsor-logo-browserstack-dark.png#only-dark" style="width: 220px;" />
|
||||
@@ -48,8 +43,8 @@ title: 欢迎
|
||||
- 查看 [__简介__](./intro/index.md) 以确保您了解关键概念
|
||||
- 通过 [__快速入门__](./quickstart/index.md) 来进行设置并运行基本的 Android 测试
|
||||
- 访问 [__生态系统__](./ecosystem/index.md) 页面,获取您可能想要使用的驱动程序、客户端和插件列表
|
||||
- 参考 [__CLI Reference__](./cli/index.md) 以了解如何从命令行使用Appium
|
||||
- 参考 [__Command Reference__](./commands/index.md) 以了解有关Appium和插件的命令列表
|
||||
- 参考 [__命令行参考__](./cli/index.md) 以了解如何从命令行使用Appium
|
||||
- 参考 [__命令参考__](./commands/index.md) 以了解有关Appium和插件的命令列表
|
||||
- 阅读不同的 [__指南__](./guides/migrating-1-to-2.md),了解各种说明、提示和技巧
|
||||
- 查看各种第三方 [__资源__](./resources.md) 以探索网络上的Appium
|
||||
- 要创建自己的Appium扩展,请参阅 [__开发者__](./developing/index.md) 文档
|
||||
|
||||
@@ -47,109 +47,52 @@ async setUrl(url) {
|
||||
|
||||
## 自动化映射
|
||||
|
||||
But *typically* what driver authors want to do is to provide automation behaviours for a given
|
||||
platform(s) that are semantically very similar to the the WebDriver spec implementations for
|
||||
browsers. When you want to find an element, you should get a reference to a UI element. When you
|
||||
want to click or tap that element, the resulting behaviour should be the same as if a person were
|
||||
to click or tap on the element. And so on.
|
||||
但通常驱动程序作者想要做的是为给定的平台提供自动化行为,这些行为在语义上与浏览器的WebDriver规范实现非常相似。当你想找到一个元素时,您应该得到一个对UI元素的引用。当您想要点击或轻触那个元素时,其产生的行为应该与一个人点击或轻触该元素时的行为相同。以此类推。
|
||||
|
||||
So the real challenge for driver authors is not how to work with the WebDriver protocol (because
|
||||
`BaseDriver` encapsulates all that for you), but how to make the actual automation happen on the
|
||||
target platform. Every driver relies on its own set of underlying technologies here. As mentioned
|
||||
in the [Overview](index.md), the iOS driver uses an Apple technology called
|
||||
[XCUITest](https://developer.apple.com/documentation/xctest/xcuielement). These underlying
|
||||
automation technologies usually have proprietary or idiosyncratic APIs of their own. Writing
|
||||
a driver becomes the task of mapping the WebDriver protocol to this underlying API (or sometimes
|
||||
a set of different underlying APIs--for example, the UiAutomator2 driver relies not only on the
|
||||
[UiAutomator2](https://developer.android.com/training/testing/other-components/ui-automator)
|
||||
technology from Google, but also functions only available through
|
||||
[ADB](https://developer.android.com/tools/adb), as well as functions only available
|
||||
via the Android SDK inside a helper app). Tying it all together into a single, usable, WebDriver
|
||||
interface is the incredibly useful (but incredibly challenging) art of driver development!
|
||||
因此,驱动程序作者面临的真正挑战不是如何使用WebDriver协议(因为`BaseDriver`已经为您封装了所有),而是如何在目标平台上实现实际的自动化。每个驱动程序都依赖于自己的一套底层技术。正如[概述](index.md)中提到的,iOS驱动程序使用了一种名为[XCUITest](https://developer.apple.com/documentation/xctest/xcuielement)的苹果技术。这些底层自动化技术通常具有自己的专有或特殊API。编写驱动程序变成了将WebDriver协议映射到该底层API的任务(或者有时是一组不同的底层API,例如UiAutomator 2驱动程序不仅依赖于Google的[UiAutomator 2](https://developer.android.com/training/testing/other-components/ui-automator)技术,而且还具有仅通过[ADB](https://developer.android.com/tools/adb)提供的功能,以及仅通过Android SDK在助手应用程序中提供的功能)。将所有内容整合到一个可用的WebDriver界面中,是驱动程序开发中非常有用(但极具挑战性)的艺术!
|
||||
|
||||
## 多层架构
|
||||
|
||||
In practice, this often results in a pretty complex architecture. Let's take iOS for example again.
|
||||
The XCUITest framework (the one used by the Appium driver) expects code that calls it to be written
|
||||
in Objective-C or Swift. Furthermore, XCUITest code can only be run in a special mode triggered by
|
||||
Xcode (and directly or indirectly, the Xcode command line tools). In other words, there's no
|
||||
straightforward way to go from a Node.js function implementation (like `setUrl()` above) to
|
||||
XCUITest API calls.
|
||||
在实践中,这通常会导致相当复杂的架构。让我们再次以iOS为例,XCUITest框架(Appium驱动程序使用的那个)期望调用它的代码是用Objective-C或Swift编写的。此外,XCUITest代码只能在Xcode(以及直接或间接的Xcode命令行工具)触发的特殊模式下运行。换句话说,没有简单的方法可以从Node.js函数实现(例如上面的`setUrl()`)到XCUITest API调用。
|
||||
|
||||
What the XCUITest driver authors have done is instead to split the driver into two parts: one part
|
||||
written in Node.js (the part which is incorporated into Appium and which initially handles the
|
||||
WebDriver commands), and the other part written in Objective-C (the part which actually gets run on
|
||||
an iOS device and makes XCUITest API calls). This makes interfacing with XCUITest possible, but
|
||||
introduces the new problem of coordination between the two parts.
|
||||
XCUITest驱动程序的作者所做的是将驱动程序分为两部分:一部分用Node.js编写(这部分被合并到Appium中,用于处理WebDriver命令),另一部分用Objective-C编写(这一部分实际上在iOS设备上运行,并进行XCUITest API调用)。这使得实现与XCUITest交互的接口成为可能,但引入了两个部分之间协调的新问题。
|
||||
|
||||
The driver authors could have chosen any of a number of very different strategies to model the
|
||||
communication between the Node.js side and the Objective-C side, but at the end of the day decided
|
||||
to use ... the WebDriver protocol! That's right, the Objective-C side of the XCUITest driver is
|
||||
itself a WebDriver implementation, called
|
||||
[WebDriverAgent](https://github.com/appium/webdriveragent).[^3]
|
||||
驱动程序作者可以选择许多非常不同的策略中的任何一种来模拟Node.js端和Objective-C端之间的通信,但最终决定使用WebDriver协议!没错,XCUITest驱动程序的Objective-C端本身就是一个WebDriver实现,称为[WebDriverAgent](https://github.com/appium/webdriveragent).[^3]。
|
||||
|
||||
[^3]: You could in theory, therefore, point your WebDriver client straight to WebDriverAgent and
|
||||
bypass Appium entirely. This is usually not convenient, however, for a few reasons:
|
||||
[^3]: 因此,从理论上讲,您可以将WebDriver客户端直接指向WebDriverAgent并完全绕过Appium。然而,这通常不方便,原因有几个:
|
||||
|
||||
- The Appium XCUITest driver builds and manages WebDriverAgent for you, which can be a pain and
|
||||
involves the use of Xcode.
|
||||
- The XCUITest driver does lots more than what can be done by WebDriverAgent, for example working
|
||||
with simulators or devices, installing apps, and the like.
|
||||
- Appium的XCUITest驱动程序为您构建和管理WebDriverAgent,这可能是个麻烦事,并且涉及到使用Xcode。
|
||||
|
||||
The moral of the story is that driver architectures can become quite complicated and multilayered,
|
||||
due to the nature of the problem we're trying to solve. It also means it can be difficult sometimes
|
||||
to tell where in this chain of technologies something has gone wrong, if you run into a problem
|
||||
with a particular test. With the XCUITest world again, we have something like the following set of
|
||||
technologies all in play at the same time:
|
||||
- XCUITest驱动程序的功能比WebDriverAgent要多得多,例如使用模拟器或设备、安装应用程序等。
|
||||
|
||||
- Your test code (in its programming language) - owned by you
|
||||
- The Appium client library - owned by Appium
|
||||
- The Selenium client library - owned by Selenium
|
||||
- The network (local or Internet)
|
||||
- The Appium server - owned by Appium
|
||||
- The Appium XCUITest driver - owned by Appium
|
||||
- WebDriverAgent - owned by Appium
|
||||
- Xcode - owned by Apple
|
||||
- XCUITest - owned by Apple
|
||||
- iOS itself - owned by Apple
|
||||
- macOS (where Xcode and iOS simulators run) - owned by Apple
|
||||
这个故事的寓意是,由于我们试图解决的问题的性质,驱动程序架构可能会变得非常复杂和多层次。这也意味着,如果你在特定的测试中遇到问题,有时很难判断这一技术链中哪里出了问题。在XCUITest世界中,我们有以下几项技术同时发挥作用:
|
||||
|
||||
It's a pretty deep stack!
|
||||
- 您的测试代码(使用相应的编程语言) - 由您拥有
|
||||
- Appium客户端库 - 由Appium拥有
|
||||
- Selenium客户端库 - 由Selenium拥有
|
||||
- 网络(本地或Internet)
|
||||
- Appium服务器 - 由Appium拥有
|
||||
- Appium XCUITest驱动程序 - 由Appium拥有
|
||||
- WebDriverAgent - 由Appium拥有
|
||||
- Xcode - 由Apple拥有
|
||||
- XCUITest - 由Apple拥有
|
||||
- iOS本身 - 由Apple拥有
|
||||
- macOS(运行Xcode和iOS模拟器的地方)- 由Apple拥有
|
||||
|
||||
这是一个相当深的堆栈!
|
||||
|
||||
## 代理模式
|
||||
|
||||
There's one other important architectural aspect of drivers to understand. It can be exemplified
|
||||
again by the XCUITest driver. Recall that we just discussed how the two "halves" of the XCUITest
|
||||
driver both speak the WebDriver protocol---the Node.js half clicks right into Appium's WebDriver
|
||||
server, and the Objective-c half (WebDriverAgent) is its own WebDriver implementation.
|
||||
驱动程序还有另一个重要的架构方面需要理解。XCUITest驱动程序再次证明了这一点。回想一下,我们刚刚讨论了XCUITest驱动程序的两个“部分”是如何使用WebDriver协议的,Node.js部分直接点击Appium的WebDriver服务器,而Objective-c部分(WebDriverAgent)是它自己的WebDriver实现。
|
||||
|
||||
This opens up the possibility of Appium taking a shortcut in certain cases. Let's imagine that the
|
||||
XCUITest driver needs to implement the `Click Element` command. The internal code of this
|
||||
implementation would look something like taking the appropriate parameters and constructing an HTTP
|
||||
request to the WebDriverAgent server. In this case, we're basically just reconstructing the
|
||||
client's original call to the Appium server![^4] So there's really no need to even write a function
|
||||
implementing the `Click Element` command. Instead, the XCUITest driver can just let Appium know
|
||||
that this command should be proxied directly to some other WebDriver server.
|
||||
这为Appium在某些情况下走捷径提供了可能性。假设XCUITest驱动程序需要实现`Click Element`命令。此实现的内部代码看起来类似于获取适当的参数并构造对WebDriverAgent服务器的HTTP请求。在这种情况下,我们基本上只是在重建客户端对Appium服务器的原始调用![^4] 所以实际上没有必要编写一个函数来实现`Click Element`命令,XCUITest驱动程序可以让Appium知道这个命令应该代理到其他一些WebDriver服务器。
|
||||
|
||||
[^4]: It's not *exactly* the same call, because the Appium server and the WebDriverAgent server
|
||||
will generate different session IDs, but these differences will be handled transparently.
|
||||
[^4]: 这不是完全相同的调用,因为Appium服务器和WebDriver Agent服务器将生成不同的会话ID,但这些差异将被透明地处理。
|
||||
|
||||
If you're not familiar with the concept of "proxying," in this case it just means that the XCUITest
|
||||
driver will not be involved at all in handling the command. Instead it will merely be repackaged
|
||||
and forwarded to WebDriverAgent at the protocol level, and WebDriverAgent's response will likewise
|
||||
be passed back directly to the client, without any XCUITest driver code seeing it or modifying it.
|
||||
如果你不熟悉"代理"这个概念,在这种情况下,它只是意味着XCUITest驱动程序将不参与处理命令。相反,它将仅仅被重新打包并转发到协议层的WebDriverAgent,并且WebDriverAgent的响应也将直接传回给客户端,而无需XCUITest驱动程序代码查看它或修改它。
|
||||
|
||||
This architectural pattern provides a nice bonus for driver authors who choose to deal with the
|
||||
WebDriver protocol everywhere, rather than constructing bespoke protocols. It also means that
|
||||
Appium can create wrapper drivers for any other existing WebDriver implementation very easily. If
|
||||
you look at the [Appium Safari driver](https://github.com/appium/appium-safari-driver) code, for
|
||||
example, you'll see that it implements basically no standard commands, because all of these are
|
||||
proxied directly to an underlying SafariDriver process.
|
||||
这种架构模式为驱动程序开发者提供了一个好处,使他们可以选择完全使用WebDriver协议,而不需要构建特定的协议。这也意味着Appium可以非常容易地为任何现有的WebDriver实现创建封装驱动程序。例如,如果你查看[Appium的Safari驱动程序](https://github.com/appium/appium-safari-driver)代码,你会发现它基本上没有实现任何标准命令,因为所有这些命令都直接代理到一个底层的SafariDriver进程。
|
||||
|
||||
It's important to understand that this proxying business is sometimes happening under the hood,
|
||||
because if you're ever diving into some open source driver code trying to figure out where
|
||||
a command is implemented, you might be surprised to find no implementation at all in the Node.js
|
||||
driver code itself! In that case, you'll need to figure out where commands are being proxied to so
|
||||
you can look there for the appropriate implementation.
|
||||
理解这种代理机制在幕后运行有时非常重要,因为如果你深入研究一些开源驱动程序代码,试图找出命令是在哪里实现的,你可能会惊讶地发现Node.js驱动程序代码中根本没有任何实现!在这种情况下,你需要弄清楚命令被代理到哪里,以便在那里查找相应的实现。
|
||||
|
||||
OK, that's enough for this very detailed introduction to drivers!
|
||||
好了,这就是关于驱动程序的详细介绍的全部内容!
|
||||
|
||||
@@ -1,6 +1,109 @@
|
||||
---
|
||||
title: Appium 项目历史
|
||||
title: Appium项目历史
|
||||
---
|
||||
|
||||
自2012年以来,Appium一直以某种形式存在。它受到各种个人和组织的指导,甚至以3种不同的编程语言实现!
|
||||
欢迎了解比您想了解的更多关于Appium是如何成为今天的样子的..
|
||||
|
||||
TODO
|
||||
## 早期灵感
|
||||
|
||||
[Dan Cuellar](https://twitter.com/thedancuellar)于2011年担任Zoosk的测试经理,当时他遇到了一个问题,iOS产品的测试通过时间已经失控。
|
||||
减少测试是一种选择,但会带来额外的风险,特别是需要几天时间才能通过iOS App Store审查流程获得补丁。
|
||||
他回想起自己在网站上工作的日子,意识到自动化就是答案。
|
||||
|
||||
Dan对现有的工具进行了调查,结果发现它们都存在重大缺陷。苹果公司提供的UIAutomation工具要求测试用JavaScript编写,不允许实时调试或解释。
|
||||
它还必须在Xcode分析工具Instruments中执行。其他第三方工具使用私有API,并要求将SDK和HTTP服务器嵌入到应用程序中。这似乎非常不可取。
|
||||
|
||||
Dan对现有的选择不满意,他要求经理再给他一些时间,看看他是否能找到更好的方法。
|
||||
他花了两周时间四处探索,看看是否有办法使用经过批准的苹果技术来自动化iOS应用程序。
|
||||
他尝试的第一个实现是使用AppleScript通过OS X可访问性API向Mac UI元素发送消息。
|
||||
这在一定程度上奏效了,但永远不会在真实设备上奏效,更不用说其他缺点了。
|
||||
|
||||
所以他想,如果我能让UIAutomation框架像解释器一样实时运行呢?他对此进行了研究,并确定他需要做的就是找到一种方法,
|
||||
从UIAutomation javascript程序中接收、执行和回复命令。使用苹果提供的用于执行shell命令的实用程序,他能够按顺序扫描文本文件以接收命令,
|
||||
`eval()`输出以执行命令,并用python将它们写回磁盘。然后,他用C#编写了实现Selenium风格语法的代码,以编写顺序排列的javascript命令。
|
||||
iOSAuto诞生了。
|
||||
|
||||
## 2012年Selenium会议
|
||||
|
||||
Dan被选中在2012年伦敦的Selenium大会上演讲,讨论一个完全不同的话题。
|
||||
在他的演讲中,他展示了如何使用Selenium语法进行iOS自动化,演示了编写平台无关的测试,同时使用具有共同接口的不同平台特定页面对象。
|
||||
令他惊讶的是,这种酷炫的测试架构却被iOS测试像WebDriver测试一样运行的场面掩盖了。
|
||||
几个人建议他在会议后再做一个闪电演讲,详细解释一下这个工作原理。
|
||||
|
||||
在会议的第二天,Dan登上舞台进行闪电演讲。Selenium的共同创始人Jason Huggins主持了闪电演讲。
|
||||
Dan在加载演示文稿时遇到了技术问题,Jason差点转到下一个闪电演讲。就在最后一刻,屏幕打开了,Dan迅速进入了他的演讲。
|
||||
他详细解释了他的实现细节和工作原理,恳求贡献者,并在五分钟内结束了演讲。观众礼貌地鼓掌,他离开了舞台。
|
||||
|
||||
## 电话响了
|
||||
|
||||
在Selenium大会四个月后,Jason给Dan打了电话。Jason一直在为Sauce Labs的一位客户提供iOS测试支持。
|
||||
Jason记得Dan的闪电演讲,认为这个项目可能对Jason的工作有帮助,但Dan的源代码并没有公开。
|
||||
于是Jason邀请Dan见一面。那一周的晚些时候,Dan在旧金山的一家酒吧遇到了Jason,并向他展示了iOSAuto的源代码。
|
||||
|
||||
Jason是一位长期的开源倡导者,他鼓励Dan在开源许可证下发布他的代码。
|
||||
8月,Dan在GitHub上发布了C#版本的[源代码](https://github.com/penguinho/appium-old/commit/3ab56d3a5601897b2790b5256351f9b5af3f9e90)。
|
||||
Jason鼓励Dan改变开发语言,使该项目对潜在贡献者更具吸引力。
|
||||
Dan上传了基于Python实现的[新版本](https://github.com/penguinho/appium-old/commit/9b891207be0957bf209a77242750da17d3eb8eda)。
|
||||
9月,Jason添加了一个Web服务器,并开始通过HTTP实现[WebDriver有线协议](https://github.com/hugs/appium-old/commit/ae8fe4578640d9af9137d0546190fa29317d1499),
|
||||
使iOSAuto可以从任何语言的任何Selenium WebDriver客户端库编写脚本。
|
||||
|
||||
## 移动测试峰会
|
||||
|
||||
Jason决定在11月的[移动测试峰会](https://twitter.com/mobtestsummit)上展示该项目,但建议先给该项目取一个新名字。
|
||||
许多想法被抛弃了,他们最终选择了AppleCart。一天后,当Jason在浏览苹果公司关于版权和商标的一些指导时,他注意到,
|
||||
在苹果公司会捍卫其商标的名称示例部分,第一个例子是“AppleCart”。
|
||||
他打电话给Dan,告知了这一情况,然后他们一起头脑风暴了一会儿,接着Jason突然想到了一个绝妙的主意。Appium... Selenium for Apps。
|
||||
|
||||
## Sauce Labs和Node.js
|
||||
|
||||
2013年1月,在移动测试峰会后不久,Sauce Labs决定全力支持Appium,并提供更多的开发能力,
|
||||
他们成立了一个工作小组,评估了项目的当前状态以及如何更好地推进项目。
|
||||
包括Jonathan Lipps(现任项目负责人)在内的团队认为Appium需要重生,并决定使用Node.js作为框架。
|
||||
Node.js是众所周知的快速高效的web服务器后端,而归根结底,Appium只是一个高度专业化的web服务器。
|
||||
同时JavaScript是一种非常容易使用的编程语言,这能让Appium比桌面上的其他选项,更容易地吸引更多开发者加入社区。
|
||||
|
||||
短短几天内,团队基于Appium的现有功能,开发了一个新版本的Appium,他的功能与之前的Python版本一样多。
|
||||
这为Appium的基本架构奠定了基础,此后我们一直在此基础上成功地进行建设。
|
||||
冲刺开发几周后,Jonathan Lipps被正式指定为项目负责人,他开始制定战略,如何让更多的人参与Appium的开发。
|
||||
|
||||
## Appium环游世界
|
||||
|
||||
最终Jonathan决定,让Appium在会议和聚会上,尽可能多的在开发人员面前展示,是吸引用户和贡献的最佳方式。
|
||||
Appium在[2013年谷歌测试自动化大会](https://www.youtube.com/watch?v=1J0aXDbjiUE)上首次亮相。
|
||||
2013年晚些时候,Appium在美国各地以及英国、波兰、葡萄牙和澳大利亚的会议和聚会上亮相。
|
||||
值得注意的是,Jonathan让Appium[像乐队中的乐器一样进行表演](https://www.youtube.com/watch?v=zsbNVkayYRQ),
|
||||
而Dan Cuellar为Selenium大会制作了一个有趣的[Appium视频混剪](https://www.youtube.com/watch?v=xkzrEn0v0II)。
|
||||
|
||||
在所有这些演讲和会议中,项目仍在继续发展。2013年初,我们发布了对Android和Selendroid的支持,使Appium成为第一个真正的跨平台自动化框架。
|
||||
该项目也继续吸引用户和贡献者,到2013年底,我们已经有1000多个提交。
|
||||
|
||||
## 通往Appium 1.0之路
|
||||
|
||||
Appium开始显著生长和成熟。2014年5月,我们发布了Appium 1.0,这是Appium发展的一个里程碑。Appium获得了
|
||||
[各种](https://www.prnewswire.com/news-releases/black-duck-announces-black-duck-open-source-rookies-of-the-year-winners-242383341.html)
|
||||
[奖项](https://www.infoworld.com/article/2241247/164642-bossie-awards-2014-the-best-open-source-application-development-tools.html),
|
||||
成为最受欢迎的开源跨平台移动自动化框架。稳定性得到改善,错误得到优先处理和修复,并添加了新的功能。
|
||||
Sauce Labs增加了捐赠给Appium开发人员的数量,但整个社区都参与了项目的指导和贡献,
|
||||
项目治理继续在公开的公共邮件列表和GitHub的问题跟踪器上进行。
|
||||
|
||||
## Appium的生态圈在扩大
|
||||
|
||||
很明显Appium的代码库,并没有为一个由分散的、不定时贡献者组成的大型团队进行优化。我们作为提交者抓住了这个机会,从头开始重写Appium,
|
||||
使用更现代的JavaScript语言版本,并重新设计了Appium的架构,以便用户或第三方开发者能够轻松构建他们自己的Appium驱动程序。
|
||||
我们希望新的贡献者能够更容易地熟悉Appium的代码库,并看到,除了核心团队之外,还有其他团体为Appium增加对新平台的支持。
|
||||
这一愿景已经开始实现,像微软和Youi.tv这样的团队,分别为Windows桌面应用自动化和Youi.tv应用自动化增加了驱动程序。
|
||||
谁知道接下来会添加哪些平台呢?
|
||||
|
||||
## Appium走向大众
|
||||
|
||||
在2016年末,Sauce Labs将Appium作为一个项目捐赠给了[JS Foundation](https://js.foundation),
|
||||
以此来向世界证明Sauce致力于保持Appium的开源状态。JS Foundation是一个非营利性的开源管理组织,负责持有开源项目的版权,并确保它们在社区中能够长期地发展。
|
||||
随着我们转移到这个非营利性基金会,我们希望对新的参与者能够更加敞开大门,无论是作为个人还是作为对Appium发展感兴趣的众多公司之一。
|
||||
|
||||
最终,JS Foundation合并到了[OpenJS Foundation](https://openjsf.org)中,而Appium是该基金会的一个有影响力的项目。
|
||||
|
||||
## Appium 2.0
|
||||
|
||||
Appium 2于2023年发布,它将重点放在将Appium作为一个生态系统而不是单一的项目上。任何人都可以开发和共享驱动程序和插件,
|
||||
这为实现iOS和Android之外的平台自动化开发,开辟了无限的可能性。
|
||||
|
||||
@@ -2,28 +2,23 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: System Requirements
|
||||
title: 系统要求
|
||||
---
|
||||
|
||||
The basic requirements for the Appium server are:
|
||||
Appium服务器的基本要求是:
|
||||
|
||||
* A macOS, Linux, or Windows operating system
|
||||
* [Node.js](https://nodejs.org) version in the [SemVer](https://semver.org) range `^14.17.0 || ^16.13.0 || >=18.0.0`
|
||||
* LTS is recommended
|
||||
* [`npm`](https://npmjs.com) version `>=8` (`npm` is usually bundled with Node.js, but can be upgraded
|
||||
independently)
|
||||
* macOS、Linux或Windows操作系统
|
||||
* [Node.js](https://nodejs.org) 版本在 `^14.17.0 || ^16.13.0 || >=18.0.0` 范围内
|
||||
* 推荐使用LTS版本
|
||||
* [`npm`](https://npmjs.com) 版本 `>=8` (`npm` 通常与Node.js捆绑在一起,但可以独立升级)
|
||||
|
||||
By itself, Appium is relatively lightweight and doesn't have significant disk space or RAM
|
||||
requirements. It can even be run in resource-constrained environments like Raspberry Pi, so long as
|
||||
Node.js is available.
|
||||
Appium本身相对轻量级,并且没有大量的磁盘空间或RAM要求。
|
||||
只要Node.js可用,它甚至可以在Raspberry Pi等资源有限的环境中运行。
|
||||
|
||||
### Driver Requirements
|
||||
### 驱动程序要求
|
||||
|
||||
Drivers for automating specific platforms will likely have other requirements. Refer to the
|
||||
documentation of the [Appium driver(s)](../ecosystem/drivers.md) for that platform for additional
|
||||
dependencies. It is almost universally the case that Appium drivers for a given platform will
|
||||
require the developer toolchain and SDKs for that platform to be installed.
|
||||
自动化特定平台的驱动程序可能还有其他要求。有关其他依赖关系,请参阅该平台的[Appium驱动程序](../ecosystem/drivers.md)文档。
|
||||
一般情况下,给定平台的Appium驱动程序需要安装该平台的开发人员工具链和SDK。
|
||||
|
||||
In order to assist with driver requirements, each (official) driver comes with the Appium Doctor tool,
|
||||
which allows to verify if all requirements have been set up. Learn more about how to use this tool in
|
||||
the [Command-Line Usage documentation](../cli/extensions.md#doctor).
|
||||
为了协助满足驱动程序的要求,每个官方驱动程序都会配备 Appium Doctor 工具,该工具用于验证当前配置是否已满足驱动程序的所有要求。
|
||||
您可以在[命令行使用文档](../cli/extensions.md#doctor)中了解更多关于如何使用这个工具的信息。
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Write a Test (.NET)
|
||||
title: 编写一个测试(.NET)
|
||||
---
|
||||
|
||||
The [Appium .NET Client](https://github.com/appium/dotnet-client/) is
|
||||
an official Appium client in C#. This driver is an extension of the Selenium C# client. It has all the functionalities of the regular driver, but add Appium-specific methods on top of this. The driver is available on the public NuGet Gallery as [Appium.WebDriver](https://www.nuget.org/packages/Appium.WebDriver/).
|
||||
[Appium.NET 客户端](https://github.com/appium/dotnet-client/)是 C# 中的官方 Appium 客户端。
|
||||
此驱动程序是 Selenium C# 客户端的扩展。它具有常规驱动程序的所有功能,并在此基础上添加了Appium特定的方法。
|
||||
该驱动程序可在 NuGet Gallery 上以[Appium.WebDriver](https://www.nuget.org/packages/Appium.WebDriver/)的形式提供。
|
||||
|
||||
Now, we get inside the directory and create a new [NUnit](https://nunit.org/) project. We will also add the references to the Appium.Net driver, and other dependencies.
|
||||
现在,我们进入该目录并创建一个新的[NUnit](https://nunit.org/)项目。我们还将添加对 Appium.NET 驱动程序的引用和其他依赖项。
|
||||
|
||||
```bash
|
||||
cd dotnet-client
|
||||
@@ -16,12 +17,12 @@ dotnet new nunit --name appiumtest
|
||||
|
||||
cd appiumtest
|
||||
|
||||
# This will install the latest 5.x version
|
||||
# 这将安装最新的5.x版本
|
||||
dotnet add package Appium.WebDriver --prerelease
|
||||
dotnet add package Newtonsoft.Json --version 13.0.3
|
||||
```
|
||||
|
||||
Once this is done, your project should have a placeholder file `UnitTest1.cs`. We will replace the code to include the OpenQA namespaces, an initialization of the driver, and the actual test.
|
||||
完成此操作后,您的项目应该有一个占位符文件`UnitTest1.cs`。我们将替换代码,以包含OpenQA名称空间、驱动程序的初始化和实际测试。
|
||||
|
||||
```C# title="UnitTest1.cs"
|
||||
using OpenQA.Selenium;
|
||||
@@ -47,7 +48,7 @@ public class Tests
|
||||
|
||||
driverOptions.AddAdditionalAppiumOption("appPackage", "com.android.settings");
|
||||
driverOptions.AddAdditionalAppiumOption("appActivity", ".Settings");
|
||||
// NoReset assumes the app com.google.android is preinstalled on the emulator
|
||||
// NoReset假设模拟器上预装了com.google.android应用程序
|
||||
driverOptions.AddAdditionalAppiumOption("noReset", true);
|
||||
|
||||
_driver = new AndroidDriver(serverUri, driverOptions, TimeSpan.FromSeconds(180));
|
||||
@@ -69,37 +70,31 @@ public class Tests
|
||||
}
|
||||
```
|
||||
|
||||
!!! note
|
||||
!!! 注意
|
||||
|
||||
It's not within the scope of this guide to give a complete run-down on the dotnet client
|
||||
library or everything that's happening here, so we'll leave the code itself unexplained in
|
||||
detail for now. You may want to read up particularly on Appium
|
||||
[Capabilities](../guides/caps.md) in addition to familiarizing yourself with the
|
||||
[dotnet client driver documentation](https://github.com/appium/dotnet-client/) for a fuller explanation
|
||||
of the various API commands you see and what their purpose is.
|
||||
本指南不包括对.NET客户端库或这里发生的一切进行完整的概述,因此我们暂时不详细解释代码本身。
|
||||
除了熟悉[dotnet客户端驱动程序文档](https://github.com/appium/dotnet-client/)外,
|
||||
您可能还想阅读[Appium功能](../guides/caps.md)文档,以更全面地解释您看到的各种API命令及其用途。
|
||||
|
||||
Basically, this code is doing the following:
|
||||
基本上,这段代码正在执行以下操作:
|
||||
|
||||
1. Defining a set of "Capabilities" (parameters) to send to the Appium server so Appium knows what
|
||||
kind of thing you want to automate. Some of these parameters can be overriden using environment variables.
|
||||
1. Starting an Appium session on the built-in Android settings app.
|
||||
1. Finding the "Battery" list item and clicking it.
|
||||
1. Ending the Appium session.
|
||||
1. 定义一组要发送到Appium服务器的“能力”(参数),以便Appium知道您想要自动化什么。其中一些参数可以使用环境变量覆盖。
|
||||
1. 在内置的Android设置应用程序上启动Appium会话。
|
||||
1. 找到“电池”列表项并单击它。
|
||||
1. 结束Appium会话。
|
||||
|
||||
That's it! Let's give it a try. Before you run the test, make sure that you have an Appium server
|
||||
running in another terminal session, otherwise you'll get an error about not being able to connect
|
||||
to one. Then, you can execute the script:
|
||||
就是这样!让我们试试。在运行测试之前,请确保您在另一个终端会话中运行了 Appium 服务器,否则您将收到无法连接到该服务器的错误。然后,您可以执行脚本:
|
||||
|
||||
```bash
|
||||
dotnet test
|
||||
|
||||
# Example output:
|
||||
# 示例输出:
|
||||
# Starting test execution, please wait...
|
||||
# A total of 1 test files matched the specified pattern.
|
||||
|
||||
# Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: 323 ms - appiumtest.dll (net7.0)
|
||||
```
|
||||
|
||||
If all goes well, you'll see the Settings app open up and navigate to the "Battery" view in the emulator before the app closes again.
|
||||
如果一切顺利,您会看到“设置”应用程序打开,并导航到模拟器中的“电池”视图,然后应用程序关闭。
|
||||
|
||||
Congratulations, you've started your Appium journey! Read on for some [next steps](./next-steps.md) to explore.
|
||||
恭喜,您已经开始了您的Appium之旅!请继续阅读,了解[下一步](./next-steps.md)要探索的内容。
|
||||
|
||||
@@ -2,82 +2,77 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Write a Test (Ruby)
|
||||
title: 编写一个测试(Ruby)
|
||||
---
|
||||
|
||||
[AppiumLib](https://github.com/appium/ruby_lib) 和 [AppiumLibCore](https://github.com/appium/ruby_lib_core)(**推荐**)是 Ruby 中的官方 Appium 客户端库,
|
||||
它们可以通过 gem 在 [appium_lib](https://rubygems.org/gems/appium_lib) 和 [appium_lib_core](https://rubygems.org/gems/appium_lib_core) 包名称下获得。
|
||||
appium_lib_core 继承自 Selenium Ruby,appium_lib 继承自 appium_lib_core,因此安装这些库时包括 Selenium 绑定。
|
||||
如果您需要不太复杂的客户端解决方案,我们建议您使用`appium_lib_core`。`appium_lib`有一些`appium_lib_core`没有的有用方法,
|
||||
但代价是更高的复杂性和历史方法,这些方法可能无法在最新环境中工作。
|
||||
|
||||
The [AppiumLib](https://github.com/appium/ruby_lib) and the [AppiumLibCore](https://github.com/appium/ruby_lib_core) (**recommended**) are official Appium client libraries in Ruby, which are available via gem under the [appium_lib](https://rubygems.org/gems/appium_lib) and the [appium_lib_core](https://rubygems.org/gems/appium_lib_core) package names. The appium_lib_core inherits from the Selenium Ruby Binding, and the appium_lib inherits from the appium_lib_core, so installing these libraries include the selenium binding. We recommend `appium_lib_core` if you need a less complex client-side solution. The `appium_lib` has some useful methods the core does not have, but for the cost of greater complexity and historical methods which may not work in the latest environment.
|
||||
|
||||
As the first step, let's initialize a Gemfile to manage the dependency:
|
||||
第一步,让我们初始化Gemfile来管理依赖项:
|
||||
|
||||
```bash
|
||||
bundle init
|
||||
```
|
||||
|
||||
Then, you could add Appium Ruby Client dependency as below:
|
||||
然后,您可以添加Appium Ruby客户端依赖项,如下所示:
|
||||
|
||||
```bash
|
||||
bundle add appium_lib_core
|
||||
# or
|
||||
# 或
|
||||
# bundle add appium_lib
|
||||
```
|
||||
|
||||
Test code example below uses `test-unit` module, thus please run:
|
||||
下面的测试代码示例使用`test-unit`模块,因此请运行:
|
||||
|
||||
```bash
|
||||
bundle add test-unit
|
||||
```
|
||||
|
||||
Once these steps has done, your `Gemfile` file should include:
|
||||
完成这些步骤后,您的`Gemfile`文件应该包括:
|
||||
|
||||
```ruby title="Gemfile"
|
||||
--8<-- "./sample-code/quickstarts/rb/Gemfile"
|
||||
```
|
||||
|
||||
The `appium_lib_core` is the main part as an Appium client.
|
||||
`appium_lib` has various helper methods, but the driver instance was ordinary designed to be used as a global variable. It could causes an issue to handle the instance.
|
||||
`appium_lib_core` does not have such a global variable.
|
||||
`appium_lib_core`是 appium 客户端的主要部分。`appium_lib`有各种辅助方法,但驱动程序实例通常被设计为全局变量。
|
||||
这可能会导致处理实例时出现问题。`appiumlib_core`中没有这样的全局变量。
|
||||
|
||||
This example is by the `appium_lib_core` with `test-unit` gem module.
|
||||
Tes code in `appium_lib` should be similar.
|
||||
这个例子使用了`appium_lib_core`和`test-unit`gem 模块。使用`appium_lib`的代码应该类似。
|
||||
|
||||
```ruby title="test.rb"
|
||||
--8<-- "./sample-code/quickstarts/rb/test.rb"
|
||||
```
|
||||
|
||||
!!! note
|
||||
!!! 注意
|
||||
|
||||
It's not within the scope of this guide to give a complete run-down on the Ruby client
|
||||
library or everything that's happening here, so we'll leave the code itself unexplained in detail for now.
|
||||
本指南不包括对Ruby客户端库或这里发生的一切进行完整的概述,因此我们暂时不详细解释代码本身。
|
||||
|
||||
- 您可能想特别了解[Appium功能](../guides/caps.md)。
|
||||
- 在 appium_lib_core 的 GitHub 仓库中,[功能测试代码](https://github.com/appium/ruby_lib_core/tree/master/test/functional)里可以找到更多的示例。
|
||||
- 在[appium_lib_core](https://www.rubydoc.info/github/appium/ruby_lib_core) 和 [appium_lib](https://www.rubydoc.info/github/appium/ruby_lib) 的文档中也可以帮你找到可用的方法。
|
||||
|
||||
!!! 注意
|
||||
|
||||
- You may want to read up particularly on Appium [Capabilities](../guides/caps.md).
|
||||
- [functional test code](https://github.com/appium/ruby_lib_core/tree/master/test/functional) in the appium_lib_core GitHub repository should help to find more working example.
|
||||
- Documentation [appium_lib_core](https://www.rubydoc.info/github/appium/ruby_lib_core) and [appium_lib](https://www.rubydoc.info/github/appium/ruby_lib) also helps to find available methods.
|
||||
示例代码可从[GitHub Appium存储库](https://github.com/appium/appium/tree/master/packages/appium/sample-code/quickstarts/rb)获得。
|
||||
|
||||
!!! note
|
||||
基本上,这段代码正在执行以下操作:
|
||||
|
||||
The sample code is available from [GitHub Appium repository](https://github.com/appium/appium/tree/master/packages/appium/sample-code/quickstarts/rb).
|
||||
1. 定义一组要发送到Appium服务器的“能力”(参数),以便Appium知道您想要自动化什么。
|
||||
1. 在内置的Android设置应用程序上启动Appium会话。
|
||||
1. 找到“电池”列表项并单击它。
|
||||
1. 暂停片刻,纯粹是为了视觉效果。
|
||||
1. 结束Appium会话。
|
||||
|
||||
|
||||
Basically, this code is doing the following:
|
||||
|
||||
1. Defining a set of "Capabilities" (parameters) to send to the Appium server so Appium knows what
|
||||
kind of thing you want to automate.
|
||||
1. Starting an Appium session on the built-in Android settings app.
|
||||
1. Finding the "Battery" list item and clicking it.
|
||||
1. Pausing for a moment purely for visual effect.
|
||||
1. Ending the Appium session.
|
||||
|
||||
That's it! Let's give it a try. Before you run the test, make sure that you have an Appium server
|
||||
running in another terminal session, otherwise you'll get an error about not being able to connect
|
||||
to one. Then, you can execute the script:
|
||||
就是这样!让我们试试。在运行测试之前,请确保您在另一个终端会话中运行了 Appium 服务器,否则您将收到无法连接到该服务器的错误。然后,您可以执行脚本:
|
||||
|
||||
```bash
|
||||
# Please run "bundle install" first if your environment has not run the installation command yet.
|
||||
# 如果您的环境尚未运行安装命令,请首先运行“bundle install”。
|
||||
bundle exec ruby test.rb
|
||||
```
|
||||
|
||||
If all goes well, you'll see the Settings app open up and navigate to the "Battery" view before the
|
||||
app closes again.
|
||||
如果一切顺利,您会看到“设置”应用程序打开,并导航到“电池”视图,然后应用程序关闭。
|
||||
|
||||
Congratulations, you've started your Appium journey! Read on for some [next steps](./next-steps.md) to explore.
|
||||
恭喜,您已经开始了您的Appium之旅!请继续阅读,了解[下一步](./next-steps.md)要探索的内容。
|
||||
|
||||
@@ -19,7 +19,7 @@ title: 安装 UiAutomator2 驱动
|
||||
### Android SDK
|
||||
|
||||
- 设置 Android SDK 要求的最简单方法是下载 [Android Studio](https://developer.android.com/studio)。
|
||||
我们需要使用其 SDK 管理器 (_设置 -> 外观和行为 -> 系统设置 -> Android SDK_) 来下载以下项目:
|
||||
我们需要使用其 SDK 管理器 (_设置 -> 语言和框架 -> Android SDK_) 来下载以下项目:
|
||||
- Android SDK 平台(选择我们想要自动化的任何 Android 平台,例如,API 级别 30)
|
||||
- Android SDK 平台工具
|
||||
- 如果愿意,你也可以不通过 Android Studio 下载这些项目:
|
||||
|
||||
@@ -15,11 +15,20 @@ import {
|
||||
promoteAppiumOptionsForObject,
|
||||
} from '@appium/base-driver';
|
||||
import AsyncLock from 'async-lock';
|
||||
import {parseCapsForInnerDriver, pullSettings, makeNonW3cCapsError} from './utils';
|
||||
import {
|
||||
parseCapsForInnerDriver,
|
||||
pullSettings,
|
||||
makeNonW3cCapsError,
|
||||
isBroadcastIp,
|
||||
fetchInterfaces,
|
||||
V4_BROADCAST_IP,
|
||||
validateFeatures,
|
||||
} from './utils';
|
||||
import {util, node, logger} from '@appium/support';
|
||||
import {getDefaultsForExtension} from './schema';
|
||||
import {DRIVER_TYPE, BIDI_BASE_PATH, BIDI_EVENT_NAME} from './constants';
|
||||
import WebSocket from 'ws';
|
||||
import os from 'node:os';
|
||||
|
||||
const MIN_WS_CODE_VAL = 1000;
|
||||
const MAX_WS_CODE_VAL = 1015;
|
||||
@@ -689,13 +698,13 @@ class AppiumDriver extends DriverCore {
|
||||
if (!_.isEmpty(this.args.denyInsecure)) {
|
||||
this.log.info('Explicitly preventing use of insecure features:');
|
||||
this.args.denyInsecure.map((a) => this.log.info(` ${a}`));
|
||||
driverInstance.denyInsecure = this.args.denyInsecure;
|
||||
driverInstance.denyInsecure = validateFeatures(this.args.denyInsecure);
|
||||
}
|
||||
|
||||
if (!_.isEmpty(this.args.allowInsecure)) {
|
||||
this.log.info('Explicitly enabling use of insecure features:');
|
||||
this.args.allowInsecure.map((a) => this.log.info(` ${a}`));
|
||||
driverInstance.allowInsecure = this.args.allowInsecure;
|
||||
driverInstance.allowInsecure = validateFeatures(this.args.allowInsecure);
|
||||
}
|
||||
|
||||
// Likewise, any driver-specific CLI args that were passed in should be assigned directly to
|
||||
@@ -773,9 +782,13 @@ class AppiumDriver extends DriverCore {
|
||||
// information here!
|
||||
if (dCaps.webSocketUrl && driverInstance.doesSupportBidi) {
|
||||
const {address, port, basePath} = this.args;
|
||||
const isUsingSsl = this.args.sslCertificatePath && this.args.sslKeyPath;
|
||||
const scheme = isUsingSsl ? 'wss' : 'ws';
|
||||
const bidiUrl = `${scheme}://${address}:${port}${basePath}${BIDI_BASE_PATH}/${innerSessionId}`;
|
||||
const scheme = `ws${this.server.isSecure() ? 's' : ''}`;
|
||||
const host = determineBiDiHost(address);
|
||||
const bidiUrl = `${scheme}://${host}:${port}${basePath}${BIDI_BASE_PATH}/${innerSessionId}`;
|
||||
this.log.info(
|
||||
`Upstream driver responded with webSocketUrl ${dCaps.webSocketUrl}, will rewrite to ` +
|
||||
`${bidiUrl} for response to client`
|
||||
);
|
||||
// @ts-ignore webSocketUrl gets sent by the client as a boolean, but then it is supposed
|
||||
// to come back from the server as a string. TODO figure out how to express this in our
|
||||
// capability constraint system
|
||||
@@ -1271,6 +1284,25 @@ function isAppiumDriverCommand(cmd) {
|
||||
return !isSessionCommand(cmd) || cmd === DELETE_SESSION_COMMAND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clients cannot use broadcast addresses, like 0.0.0.0 or ::
|
||||
* to create connections. Thus we prefer a hostname if such
|
||||
* address is provided or the actual address of a non-local interface,
|
||||
* in case the host only has one such interface.
|
||||
*
|
||||
* @param {string} address
|
||||
* @returns {string}
|
||||
*/
|
||||
function determineBiDiHost(address) {
|
||||
if (!isBroadcastIp(address)) {
|
||||
return address;
|
||||
}
|
||||
|
||||
const nonLocalInterfaces = fetchInterfaces(address === V4_BROADCAST_IP ? 4 : 6)
|
||||
.filter((iface) => !iface.internal);
|
||||
return nonLocalInterfaces.length === 1 ? nonLocalInterfaces[0].address : os.hostname();
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when Appium tried to proxy a command using a driver's `proxyCommand` method but the
|
||||
* method did not exist
|
||||
|
||||
@@ -311,7 +311,7 @@ class ExtensionCliCommand {
|
||||
installType,
|
||||
pkgName: /** @type {string} */ (packageName),
|
||||
};
|
||||
probableExtName = installSpec;
|
||||
probableExtName = /** @type {string} */ (packageName);
|
||||
} else if (installType === INSTALL_TYPE_GIT) {
|
||||
// git urls can have '.git' at the end, but this is not necessary and would complicate the
|
||||
// way we download and name directories, so we can just remove it
|
||||
@@ -321,7 +321,7 @@ class ExtensionCliCommand {
|
||||
installType,
|
||||
pkgName: /** @type {string} */ (packageName),
|
||||
};
|
||||
probableExtName = installSpec;
|
||||
probableExtName = /** @type {string} */ (packageName);
|
||||
} else {
|
||||
let pkgName, pkgVer;
|
||||
if (installType === INSTALL_TYPE_LOCAL) {
|
||||
@@ -439,13 +439,15 @@ class ExtensionCliCommand {
|
||||
* @returns {Promise<ExtInstallReceipt<ExtType>>}
|
||||
*/
|
||||
async installViaNpm({installSpec, pkgName, pkgVer, installType}) {
|
||||
const npmSpec = `${pkgName}${pkgVer ? '@' + pkgVer : ''}`;
|
||||
const specMsg = npmSpec === installSpec ? '' : ` using NPM install spec '${npmSpec}'`;
|
||||
const msg = `Installing '${installSpec}'${specMsg}`;
|
||||
const msg = `Installing '${installSpec}'`;
|
||||
|
||||
// the string used for installation is either <name>@<ver> in the case of a standard NPM
|
||||
// package, or whatever the user sent in otherwise.
|
||||
const installStr = installType === INSTALL_TYPE_NPM ? `${pkgName}${pkgVer ? `@${pkgVer}` : ''}` : installSpec;
|
||||
try {
|
||||
const {pkg, path} = await spinWith(this.isJsonOutput, msg, async () => {
|
||||
const {pkg, installPath: path} = await npm.installPackage(this.config.appiumHome, pkgName, {
|
||||
pkgVer,
|
||||
const {pkg, installPath: path} = await npm.installPackage(this.config.appiumHome, installStr, {
|
||||
pkgName,
|
||||
installType,
|
||||
});
|
||||
this.validatePackageJson(pkg, installSpec);
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
MOBILE_DRIVERS
|
||||
} from '../constants';
|
||||
import {runExtensionCommand} from './extension';
|
||||
import { system } from '@appium/support';
|
||||
import { system, fs } from '@appium/support';
|
||||
import log from '../logger';
|
||||
|
||||
/**
|
||||
@@ -14,6 +14,7 @@ import log from '../logger';
|
||||
export const SUBCOMMAND_MOBILE = 'mobile';
|
||||
export const SUBCOMMAND_DESKTOP = 'desktop';
|
||||
export const SUBCOMMAND_BROWSER = 'browser';
|
||||
export const SUBCOMMAND_RESET = 'reset';
|
||||
|
||||
/**
|
||||
* Pairs of preset subcommand and driver candidates.
|
||||
@@ -72,12 +73,11 @@ export function determinePlatformName() {
|
||||
* Run 'setup' command to install drivers/plugins into the given appium home.
|
||||
* @template {import('appium/types').CliCommandSetup} SetupCmd
|
||||
* @param {import('appium/types').Args<SetupCmd>} preConfigArgs
|
||||
* @param {string} appiumHome
|
||||
* @param {DriverConfig} driverConfig
|
||||
* @param {PluginConfig} pluginConfig
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function runSetupCommand(appiumHome, preConfigArgs, driverConfig, pluginConfig) {
|
||||
export async function runSetupCommand(preConfigArgs, driverConfig, pluginConfig) {
|
||||
switch (preConfigArgs.setupCommand) {
|
||||
case SUBCOMMAND_DESKTOP:
|
||||
await setupDesktopAppDrivers(driverConfig);
|
||||
@@ -87,6 +87,9 @@ export async function runSetupCommand(appiumHome, preConfigArgs, driverConfig, p
|
||||
await setupBrowserDrivers(driverConfig);
|
||||
await setupDefaultPlugins(pluginConfig);
|
||||
break;
|
||||
case SUBCOMMAND_RESET:
|
||||
await resetAllExtensions(driverConfig, pluginConfig);
|
||||
break;
|
||||
default:
|
||||
await setupMobileDrivers(driverConfig);
|
||||
await setupDefaultPlugins(pluginConfig);
|
||||
@@ -94,6 +97,47 @@ export async function runSetupCommand(appiumHome, preConfigArgs, driverConfig, p
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Resets all installed drivers and extensions
|
||||
*
|
||||
* @param {DriverConfig} driverConfig
|
||||
* @param {PluginConfig} pluginConfig
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function resetAllExtensions(driverConfig, pluginConfig) {
|
||||
for (const [command, config] of [
|
||||
['driver', driverConfig],
|
||||
['plugin', pluginConfig],
|
||||
]) {
|
||||
for (const extensionName of _.keys(/** @type {DriverConfig|PluginConfig} */ (config).installedExtensions)) {
|
||||
try {
|
||||
await uninstallExtension(
|
||||
extensionName,
|
||||
extensionCommandArgs(/** @type {CliExtensionCommand} */ (command), extensionName, 'uninstall'),
|
||||
/** @type {DriverConfig|PluginConfig} */ (config)
|
||||
);
|
||||
} catch (e) {
|
||||
log.warn(
|
||||
`${extensionName} ${command} cannot be uninstalled. Will delete the manifest anyway. ` +
|
||||
`Original error: ${e.stack}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const manifestPath = /** @type {DriverConfig|PluginConfig} */ (config).manifestPath;
|
||||
if (!await fs.exists(manifestPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await fs.rimraf(manifestPath);
|
||||
if (await fs.exists(manifestPath)) {
|
||||
throw new Error(`${command} manifest at '${manifestPath}' cannot be deleted. Is it accessible?`);
|
||||
} else {
|
||||
log.info(`Successfully deleted ${command} manifest at '${manifestPath}'`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install drivers listed in DEFAULT_DRIVERS.
|
||||
* @param {DriverConfig} driverConfig
|
||||
@@ -149,7 +193,7 @@ async function setupDefaultPlugins(pluginConfig) {
|
||||
* @param {string} extensionName
|
||||
* @param {Args} extensionConfigArgs
|
||||
* @param {DriverConfig|PluginConfig} extensionConfig
|
||||
* @returns
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function installExtension(extensionName, extensionConfigArgs, extensionConfig) {
|
||||
if (_.keys(extensionConfig.installedExtensions).includes(extensionName)) {
|
||||
@@ -160,6 +204,22 @@ async function installExtension(extensionName, extensionConfigArgs, extensionCon
|
||||
await runExtensionCommand(extensionConfigArgs, extensionConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the given extensionConfigArgs command after checking if the given extensionName was already installed.
|
||||
* @param {string} extensionName
|
||||
* @param {Args} extensionConfigArgs
|
||||
* @param {DriverConfig|PluginConfig} extensionConfig
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function uninstallExtension(extensionName, extensionConfigArgs, extensionConfig) {
|
||||
if (!_.keys(extensionConfig.installedExtensions).includes(extensionName)) {
|
||||
log.info(`${extensionName} (${extensionConfig.installedExtensions[extensionName].version}) is not installed. ` +
|
||||
`Skipping its uninstall.`);
|
||||
return;
|
||||
}
|
||||
await runExtensionCommand(extensionConfigArgs, extensionConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the command config for driver or plugin.
|
||||
* @param {CliExtensionCommand} extensionCommand
|
||||
|
||||
@@ -120,7 +120,7 @@ const stripColorFormat = format(function stripColor(info) {
|
||||
return {
|
||||
...info,
|
||||
level: stripColorCodes(info.level),
|
||||
message: stripColorCodes(info.message),
|
||||
message: _.isString(info.message) ? stripColorCodes(info.message) : info.message,
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -344,7 +344,7 @@ function formatTimestamp(args) {
|
||||
* @param {string} text
|
||||
* @returns {string}
|
||||
*/
|
||||
function stripColorCodes(text) {
|
||||
export function stripColorCodes(text) {
|
||||
return text.replace(COLOR_CODE_PATTERN, '');
|
||||
}
|
||||
|
||||
|
||||
@@ -39,12 +39,20 @@ import {
|
||||
isServerCommandArgs,
|
||||
fetchInterfaces,
|
||||
V4_BROADCAST_IP,
|
||||
V6_BROADCAST_IP,
|
||||
isSetupCommandArgs,
|
||||
isBroadcastIp,
|
||||
} from './utils';
|
||||
import net from 'node:net';
|
||||
|
||||
const {resolveAppiumHome} = env;
|
||||
/*
|
||||
* By default Node.js shows a warning
|
||||
* if the actual amount of listeners exceeds the maximum amount,
|
||||
* which equals to 10 by default. It is known that multiple drivers/plugins
|
||||
* may assign custom listeners to the server process to handle, for example,
|
||||
* the graceful shutdown scenario.
|
||||
*/
|
||||
const MAX_SERVER_PROCESS_LISTENERS = 100;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -293,7 +301,7 @@ async function init(args) {
|
||||
appiumHome,
|
||||
});
|
||||
} else if (isSetupCommandArgs(preConfigArgs)) {
|
||||
await runSetupCommand(appiumHome, preConfigArgs, driverConfig, pluginConfig);
|
||||
await runSetupCommand(preConfigArgs, driverConfig, pluginConfig);
|
||||
return /** @type {InitResult<Cmd>} */ ({});
|
||||
} else {
|
||||
await requireDir(appiumHome, true, appiumHomeSourceName);
|
||||
@@ -321,7 +329,7 @@ async function init(args) {
|
||||
function logServerAddress(url) {
|
||||
const urlObj = new URL(url);
|
||||
logger.info(`Appium REST http interface listener started on ${url}`);
|
||||
if (![V4_BROADCAST_IP, V6_BROADCAST_IP, `[${V6_BROADCAST_IP}]`].includes(urlObj.hostname)) {
|
||||
if (!isBroadcastIp(urlObj.hostname)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -433,6 +441,7 @@ async function main(args) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
process.setMaxListeners(MAX_SERVER_PROCESS_LISTENERS);
|
||||
for (const signal of ['SIGINT', 'SIGTERM']) {
|
||||
process.once(signal, async function onSignal() {
|
||||
logger.info(`Received ${signal} - shutting down`);
|
||||
@@ -447,7 +456,7 @@ async function main(args) {
|
||||
});
|
||||
}
|
||||
|
||||
const protocol = 'secure' in server && server.secure ? 'https' : 'http';
|
||||
const protocol = server.isSecure() ? 'https' : 'http';
|
||||
const address = net.isIPv6(parsedArgs.address) ? `[${parsedArgs.address}]` : parsedArgs.address;
|
||||
logServerAddress(
|
||||
`${protocol}://${address}:${parsedArgs.port}${normalizeBasePath(parsedArgs.basePath)}`,
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import _ from 'lodash';
|
||||
import logger from './logger';
|
||||
import {processCapabilities, PROTOCOLS, STANDARD_CAPS, errors} from '@appium/base-driver';
|
||||
import {
|
||||
processCapabilities,
|
||||
PROTOCOLS,
|
||||
STANDARD_CAPS,
|
||||
errors,
|
||||
} from '@appium/base-driver';
|
||||
import {inspect as dump} from 'util';
|
||||
import {node, fs} from '@appium/support';
|
||||
import path from 'path';
|
||||
@@ -12,7 +17,8 @@ const STANDARD_CAPS_LOWERCASE = new Set([...STANDARD_CAPS].map((cap) => cap.toLo
|
||||
export const V4_BROADCAST_IP = '0.0.0.0';
|
||||
export const V6_BROADCAST_IP = '::';
|
||||
export const npmPackage = fs.readPackageJsonFrom(__dirname);
|
||||
|
||||
const ALL_DRIVERS_MATCH = '*';
|
||||
const FEATURE_NAME_SEPARATOR = ':';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -40,7 +46,7 @@ export function makeNonW3cCapsError() {
|
||||
*
|
||||
* @todo May want to force color to be `false` if {@link isStdoutTTY} is `false`.
|
||||
*/
|
||||
const inspect = _.flow(
|
||||
export const inspect = _.flow(
|
||||
_.partialRight(
|
||||
/** @type {(object: any, options: import('util').InspectOptions) => string} */ (dump),
|
||||
{colors: true, depth: null, compact: !isStdoutTTY}
|
||||
@@ -62,7 +68,7 @@ const inspect = _.flow(
|
||||
* @param {NSCapabilities<C>} [defaultCapabilities]
|
||||
* @returns {ParsedDriverCaps<C,J>|InvalidCaps<C,J>}
|
||||
*/
|
||||
function parseCapsForInnerDriver(
|
||||
export function parseCapsForInnerDriver(
|
||||
jsonwpCapabilities,
|
||||
w3cCapabilities,
|
||||
constraints = /** @type {C} */ ({}),
|
||||
@@ -182,7 +188,7 @@ function parseCapsForInnerDriver(
|
||||
* @param {Capabilities<C>} caps - Desired capabilities object
|
||||
* @returns {NSCapabilities<C>}
|
||||
*/
|
||||
function insertAppiumPrefixes(caps) {
|
||||
export function insertAppiumPrefixes(caps) {
|
||||
return /** @type {NSCapabilities<C>} */ (
|
||||
_.mapKeys(caps, (_, key) =>
|
||||
STANDARD_CAPS_LOWERCASE.has(key.toLowerCase()) || key.includes(':')
|
||||
@@ -197,7 +203,7 @@ function insertAppiumPrefixes(caps) {
|
||||
* @param {NSCapabilities<C>} caps
|
||||
* @returns {Capabilities<C>}
|
||||
*/
|
||||
function removeAppiumPrefixes(caps) {
|
||||
export function removeAppiumPrefixes(caps) {
|
||||
return /** @type {Capabilities<C>} */ (_.mapKeys(caps, (_, key) => removeAppiumPrefix(key)));
|
||||
}
|
||||
|
||||
@@ -215,7 +221,7 @@ function removeAppiumPrefix(key) {
|
||||
* @param {string} pkgName
|
||||
* @returns {string|undefined}
|
||||
*/
|
||||
function getPackageVersion(pkgName) {
|
||||
export function getPackageVersion(pkgName) {
|
||||
const pkgInfo = require(`${pkgName}/package.json`) || {};
|
||||
return pkgInfo.version;
|
||||
}
|
||||
@@ -227,7 +233,7 @@ function getPackageVersion(pkgName) {
|
||||
* for more details.
|
||||
* @returns {void}
|
||||
*/
|
||||
function adjustNodePath() {
|
||||
export function adjustNodePath() {
|
||||
const selfRoot = node.getModuleRootSync('appium', __filename);
|
||||
if (!selfRoot || path.dirname(selfRoot).length >= selfRoot.length) {
|
||||
return;
|
||||
@@ -297,7 +303,7 @@ function adjustNodePath() {
|
||||
* setting items or a dictionary containing parsed Appium setting names along with
|
||||
* their values.
|
||||
*/
|
||||
function pullSettings(caps) {
|
||||
export function pullSettings(caps) {
|
||||
if (!_.isPlainObject(caps) || _.isEmpty(caps)) {
|
||||
return {};
|
||||
}
|
||||
@@ -447,15 +453,46 @@ export function adler32(str, seed = null) {
|
||||
return ((b % 65521) << 16) | (a % 65521);
|
||||
}
|
||||
|
||||
export {
|
||||
inspect,
|
||||
parseCapsForInnerDriver,
|
||||
insertAppiumPrefixes,
|
||||
getPackageVersion,
|
||||
pullSettings,
|
||||
removeAppiumPrefixes,
|
||||
adjustNodePath,
|
||||
};
|
||||
/**
|
||||
* Checks if the provided address is a broadcast one.
|
||||
*
|
||||
* @param {string} address
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isBroadcastIp(address) {
|
||||
return [V4_BROADCAST_IP, V6_BROADCAST_IP, `[${V6_BROADCAST_IP}]`].includes(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the list of allowed/denied server features
|
||||
*
|
||||
* @param {string[]} features
|
||||
* @returns {string[]}
|
||||
*/
|
||||
export function validateFeatures(features) {
|
||||
const validator = (/** @type {string} */ fullName) => {
|
||||
const separatorPos = fullName.indexOf(FEATURE_NAME_SEPARATOR);
|
||||
// TODO: This is for the backward compatibility with Appium2
|
||||
// TODO: In Appium3 the separator will be mandatory
|
||||
if (separatorPos < 0) {
|
||||
return `${ALL_DRIVERS_MATCH}${FEATURE_NAME_SEPARATOR}${fullName}`;
|
||||
}
|
||||
|
||||
const [automationName, featureName] = [
|
||||
fullName.substring(0, separatorPos),
|
||||
fullName.substring(separatorPos + 1)
|
||||
];
|
||||
if (!automationName || !featureName) {
|
||||
throw new Error(
|
||||
`The full feature name must include both the destination automation name or the ` +
|
||||
`'${ALL_DRIVERS_MATCH}' wildcard to apply the feature to all installed drivers, and ` +
|
||||
`the feature name split by a colon, got '${fullName}' instead`
|
||||
);
|
||||
}
|
||||
return fullName;
|
||||
};
|
||||
return features.map(validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {import('@appium/types').StringRecord} StringRecord
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "appium",
|
||||
"version": "2.11.3",
|
||||
"version": "2.13.1",
|
||||
"description": "Automation for Apps.",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -51,6 +51,7 @@
|
||||
"dev:docs:en": "appium-docs build --serve --mkdocs-yml ./docs/mkdocs-en.yml",
|
||||
"dev:docs:ja": "appium-docs build --serve --mkdocs-yml ./docs/mkdocs-ja.yml",
|
||||
"dev:docs:zh": "appium-docs build --serve --mkdocs-yml ./docs/mkdocs-zh.yml",
|
||||
"install-docs-deps": "appium-docs init --no-mkdocs",
|
||||
"postinstall": "node ./scripts/autoinstall-extensions.js",
|
||||
"publish:docs": "cross-env APPIUM_DOCS_PUBLISH=1 npm run build:docs",
|
||||
"test": "npm run test:unit",
|
||||
@@ -59,15 +60,15 @@
|
||||
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@appium/base-driver": "^9.11.3",
|
||||
"@appium/base-plugin": "^2.2.43",
|
||||
"@appium/docutils": "^1.0.19",
|
||||
"@appium/base-driver": "^9.13.1",
|
||||
"@appium/base-plugin": "^2.2.50",
|
||||
"@appium/docutils": "^1.0.26",
|
||||
"@appium/logger": "^1.6.1",
|
||||
"@appium/schema": "^0.6.1",
|
||||
"@appium/support": "^5.1.3",
|
||||
"@appium/types": "^0.21.2",
|
||||
"@sidvind/better-ajv-errors": "2.1.3",
|
||||
"@types/argparse": "2.0.16",
|
||||
"@appium/schema": "^0.7.0",
|
||||
"@appium/support": "^6.0.0",
|
||||
"@appium/types": "^0.22.3",
|
||||
"@sidvind/better-ajv-errors": "3.0.1",
|
||||
"@types/argparse": "2.0.17",
|
||||
"@types/bluebird": "3.5.42",
|
||||
"@types/semver": "7.5.8",
|
||||
"@types/teen_process": "2.0.4",
|
||||
@@ -77,10 +78,10 @@
|
||||
"argparse": "2.0.1",
|
||||
"async-lock": "1.4.1",
|
||||
"asyncbox": "3.0.0",
|
||||
"axios": "1.7.3",
|
||||
"axios": "1.7.9",
|
||||
"bluebird": "3.7.2",
|
||||
"cross-env": "7.0.3",
|
||||
"lilconfig": "3.1.2",
|
||||
"lilconfig": "3.1.3",
|
||||
"lodash": "4.17.21",
|
||||
"lru-cache": "10.4.3",
|
||||
"ora": "5.4.1",
|
||||
@@ -88,12 +89,12 @@
|
||||
"resolve-from": "5.0.0",
|
||||
"semver": "7.6.3",
|
||||
"source-map-support": "0.5.21",
|
||||
"teen_process": "2.2.0",
|
||||
"type-fest": "4.23.0",
|
||||
"winston": "3.13.1",
|
||||
"teen_process": "2.2.2",
|
||||
"type-fest": "4.30.0",
|
||||
"winston": "3.17.0",
|
||||
"wrap-ansi": "7.0.0",
|
||||
"ws": "8.18.0",
|
||||
"yaml": "2.5.0"
|
||||
"yaml": "2.6.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"webdriverio": "8.40.0"
|
||||
"webdriverio": "8.40.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
EXECUTABLE,
|
||||
runAppiumRaw,
|
||||
} from './e2e-helpers';
|
||||
import { stripColorCodes } from '../../lib/logsink';
|
||||
|
||||
describe('argument parsing', function () {
|
||||
/**
|
||||
@@ -68,23 +69,17 @@ describe('argument parsing', function () {
|
||||
describe('when the user provides an string where a number was expected', function () {
|
||||
describe('when color output is supported', function () {
|
||||
it('should output a fancy error message', async function () {
|
||||
const [{stderr: actual}, expected] = await B.all([
|
||||
runAppiumRaw(appiumHome, ['--port=sheep'], {
|
||||
env: {FORCE_COLOR: '1'},
|
||||
}),
|
||||
readAppiumArgErrorFixture('cli/cli-error-output-color.txt'),
|
||||
]);
|
||||
expect(formatAppiumArgErrorOutput(actual)).to.equal(expected);
|
||||
const {stderr: actual} = await runAppiumRaw(appiumHome, ['--port=sheep'], {
|
||||
env: {FORCE_COLOR: '1'},
|
||||
});
|
||||
expect(stripColorCodes(actual)).to.not.equal(actual);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when color output is unsupported', function () {
|
||||
it('should output a colorless yet fancy error message', async function () {
|
||||
const [{stderr: actual}, expected] = await B.all([
|
||||
runAppiumRaw(appiumHome, ['--port=sheep'], {}),
|
||||
readAppiumArgErrorFixture('cli/cli-error-output.txt'),
|
||||
]);
|
||||
expect(formatAppiumArgErrorOutput(actual)).to.equal(expected);
|
||||
const {stderr: actual} = await runAppiumRaw(appiumHome, ['--port=sheep'], {});
|
||||
expect(stripColorCodes(actual)).to.equal(actual);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[0m[31m[1m>[22m[39m[90m 1 |[39m [32m"sheep"[39m[0m
|
||||
[0m [90m |[39m [31m[1m^[22m[39m[31m[1m^[22m[39m[31m[1m^[22m[39m[31m[1m^[22m[39m[31m[1m^[22m[39m[31m[1m^[22m[39m[31m[1m^[22m[39m [31m[1m👈🏽 [95mtype[31m must be integer[22m[39m[0m
|
||||
@@ -1,2 +0,0 @@
|
||||
> 1 | "sheep"
|
||||
| ^^^^^^^ 👈🏽 type must be integer
|
||||
@@ -19,6 +19,7 @@ export default {
|
||||
port: 4723,
|
||||
relaxedSecurityEnabled: false,
|
||||
sessionOverride: false,
|
||||
shutdownTimeout: 5000,
|
||||
strictCaps: false,
|
||||
useDrivers: [],
|
||||
usePlugins: []
|
||||
|
||||
@@ -20,7 +20,7 @@ export type CliCommand = CliCommandServer | CliExtensionCommand | CliCommandSetu
|
||||
* Possible subcommands of {@linkcode CliCommandSetup}.
|
||||
* The command name will be preset name to get drivers/plugins to be installed.
|
||||
*/
|
||||
export type CliCommandSetupSubcommand = 'mobile' | 'browser' | 'desktop';
|
||||
export type CliCommandSetupSubcommand = 'mobile' | 'browser' | 'desktop' | 'reset';
|
||||
|
||||
/**
|
||||
* Possible subcommands of {@linkcode CliCommandDriver} or
|
||||
|
||||
@@ -3,6 +3,102 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [9.13.1](https://github.com/appium/appium/compare/@appium/base-driver@9.13.0...@appium/base-driver@9.13.1) (2024-12-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **base-driver:** add * always for non-separator for backward compatibility ([#20821](https://github.com/appium/appium/issues/20821)) ([6ea0830](https://github.com/appium/appium/commit/6ea0830319c204097233d0659e21b3447b624431))
|
||||
* **base-driver:** update dependency @types/method-override to v3 ([#20799](https://github.com/appium/appium/issues/20799)) ([42ef484](https://github.com/appium/appium/commit/42ef4841f9a379d8e9ce531eb5375eab03902e3f))
|
||||
* **support:** update dependency axios to v1.7.9 ([#20811](https://github.com/appium/appium/issues/20811)) ([69f100a](https://github.com/appium/appium/commit/69f100ad3e12030708dee4b8a74005dd41976e37))
|
||||
* **types:** update dependency type-fest to v4.30.0 ([#20802](https://github.com/appium/appium/issues/20802)) ([8590432](https://github.com/appium/appium/commit/8590432955eb7663e35847db541b9ead3f845a36))
|
||||
|
||||
|
||||
|
||||
## [9.13.0](https://github.com/appium/appium/compare/@appium/base-driver@9.12.2...@appium/base-driver@9.13.0) (2024-12-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **base-driver:** Allow to prefix feature names with automation names ([#20793](https://github.com/appium/appium/issues/20793)) ([942057d](https://github.com/appium/appium/commit/942057d26cbf51539f34b6b7ff8a3c1d07821687))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **types:** update dependency type-fest to v4.29.1 ([#20795](https://github.com/appium/appium/issues/20795)) ([6ba31fe](https://github.com/appium/appium/commit/6ba31fe5766f69cb010a4cac81233f4c3cbcf80f))
|
||||
|
||||
|
||||
|
||||
## [9.12.2](https://github.com/appium/appium/compare/@appium/base-driver@9.12.1...@appium/base-driver@9.12.2) (2024-11-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **driver-test-support:** update definitelytyped ([e3bce2b](https://github.com/appium/appium/commit/e3bce2b6be0ea072ec5e8472c0e191bdfea52a06))
|
||||
* **support:** update dependency axios to v1.7.8 ([#20778](https://github.com/appium/appium/issues/20778)) ([f9920e2](https://github.com/appium/appium/commit/f9920e2c1b02e3587e5d5fa00ac59055ab57fedd))
|
||||
* **types:** update dependency type-fest to v4.27.0 ([#20754](https://github.com/appium/appium/issues/20754)) ([d6b4079](https://github.com/appium/appium/commit/d6b40797d387711df94c29984af91308da27f92b))
|
||||
* **types:** update dependency type-fest to v4.28.0 ([#20775](https://github.com/appium/appium/issues/20775)) ([a25d8f1](https://github.com/appium/appium/commit/a25d8f129c8baf76ab40ce3b8d053f7da77f14b3))
|
||||
* **types:** update dependency type-fest to v4.29.0 ([#20783](https://github.com/appium/appium/issues/20783)) ([b6aa5ac](https://github.com/appium/appium/commit/b6aa5ace6e54709dba54bc62a902d91851ab7ef1))
|
||||
|
||||
|
||||
|
||||
## [9.12.1](https://github.com/appium/appium/compare/@appium/base-driver@9.12.0...@appium/base-driver@9.12.1) (2024-10-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **driver-test-support:** update definitelytyped ([958fca4](https://github.com/appium/appium/commit/958fca47c8515664aac4c2f0b1051cadd43431b9))
|
||||
|
||||
|
||||
|
||||
## [9.12.0](https://github.com/appium/appium/compare/@appium/base-driver@9.11.5...@appium/base-driver@9.12.0) (2024-10-15)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **appium:** Make server graceful shutdown timeout configurable via command line args ([#20641](https://github.com/appium/appium/issues/20641)) ([5661888](https://github.com/appium/appium/commit/56618886ed007df3c28ce98beb4ff91bc47da2a2))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **base-driver:** update dependency express to v4.21.1 ([0e52da4](https://github.com/appium/appium/commit/0e52da4b3adbd5ecde09395063255c3af7eb0400))
|
||||
* **base-driver:** update dependency path-to-regexp to v8.2.0 ([e8886ae](https://github.com/appium/appium/commit/e8886ae0d276ac4f97a1bdb88998fc30fbd936fa))
|
||||
* **driver-test-support:** update dependency @types/lodash to v4.17.10 ([a2b0ba8](https://github.com/appium/appium/commit/a2b0ba877310737f1ebf7ecda0b9aa5d7083e1f4))
|
||||
* **types:** update dependency @types/express to v5 ([#20620](https://github.com/appium/appium/issues/20620)) ([69e9abe](https://github.com/appium/appium/commit/69e9abeed3ac5a2f61d8b7f1cd4ec4bd9c054cf1))
|
||||
|
||||
|
||||
|
||||
## [9.11.5](https://github.com/appium/appium/compare/@appium/base-driver@9.11.4...@appium/base-driver@9.11.5) (2024-09-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **appium:** Return hostname as web socket url for BiDi if a broadcast address is assigned to the server ([#20603](https://github.com/appium/appium/issues/20603)) ([f0de55d](https://github.com/appium/appium/commit/f0de55da0da2fc0305876a948704c1f0a2a5990f))
|
||||
* **driver-test-support:** update definitelytyped ([#20605](https://github.com/appium/appium/issues/20605)) ([da7a4fd](https://github.com/appium/appium/commit/da7a4fdce8790bc59370bfe4b912c7c0c403c713))
|
||||
|
||||
|
||||
|
||||
## [9.11.4](https://github.com/appium/appium/compare/@appium/base-driver@9.11.3...@appium/base-driver@9.11.4) (2024-09-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **base-driver:** Add a server flag to check if it operates a secure protocol ([#20449](https://github.com/appium/appium/issues/20449)) ([622b245](https://github.com/appium/appium/commit/622b245ea38793280d9785a59a0416ce025862fe))
|
||||
* **base-driver:** update dependency body-parser to v1.20.3 ([056baba](https://github.com/appium/appium/commit/056baba3a0c51973d5e834283355821eced6ee17))
|
||||
* **base-driver:** update dependency express to v4.20.0 ([ef163eb](https://github.com/appium/appium/commit/ef163eb8df512e89f4e62c99b32fc979008fcfaa))
|
||||
* **base-driver:** update dependency express to v4.21.0 ([cb9fb9c](https://github.com/appium/appium/commit/cb9fb9c6fef608e29284210be27356a488f4002c))
|
||||
* **base-driver:** update dependency path-to-regexp to v8 ([#20520](https://github.com/appium/appium/issues/20520)) ([63cb664](https://github.com/appium/appium/commit/63cb664af13d7411ff325095cd0e9b6fd24363c3))
|
||||
* **base-driver:** update dependency path-to-regexp to v8.1.0 ([#20562](https://github.com/appium/appium/issues/20562)) ([1cae549](https://github.com/appium/appium/commit/1cae549a7be5138e980af6661b96cd7d6268fdb0))
|
||||
* **support:** update dependency axios to v1.7.4 ([d17d022](https://github.com/appium/appium/commit/d17d0222245ab94a78e578c0398734e65a89ba68))
|
||||
* **support:** update dependency axios to v1.7.5 ([fedabb1](https://github.com/appium/appium/commit/fedabb1fdc7af10f9e4b06ea23815c4bc7c6bf5e))
|
||||
* **support:** update dependency axios to v1.7.7 ([7fe67a2](https://github.com/appium/appium/commit/7fe67a286a15a917ce3b1b47a08e982e65bbd9e4))
|
||||
* **types:** update dependency type-fest to v4 ([#20467](https://github.com/appium/appium/issues/20467)) ([482a1f7](https://github.com/appium/appium/commit/482a1f7bbfbf6478ee09bb1668b830ddbf13b143))
|
||||
* **types:** update dependency type-fest to v4 ([#20471](https://github.com/appium/appium/issues/20471)) ([9a66f48](https://github.com/appium/appium/commit/9a66f4800141cc86c90d58ca1103bab0066081bc))
|
||||
* **types:** update dependency type-fest to v4 ([#20548](https://github.com/appium/appium/issues/20548)) ([5b8cb76](https://github.com/appium/appium/commit/5b8cb76ea3cda75095e79c91539be73feeadf869))
|
||||
* **types:** update dependency type-fest to v4.26.0 ([#20511](https://github.com/appium/appium/issues/20511)) ([8f20c97](https://github.com/appium/appium/commit/8f20c973f4a6d3380163b6afd7f113808453a62d))
|
||||
|
||||
|
||||
|
||||
## [9.11.3](https://github.com/appium/appium/compare/@appium/base-driver@9.11.2...@appium/base-driver@9.11.3) (2024-08-07)
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,11 @@ import AsyncLock from 'async-lock';
|
||||
import _ from 'lodash';
|
||||
import {EventEmitter} from 'node:events';
|
||||
import os from 'node:os';
|
||||
import {DEFAULT_BASE_PATH, PROTOCOLS, MAX_LOG_BODY_LENGTH} from '../constants';
|
||||
import {
|
||||
DEFAULT_BASE_PATH,
|
||||
PROTOCOLS,
|
||||
MAX_LOG_BODY_LENGTH,
|
||||
} from '../constants';
|
||||
import {errors} from '../protocol';
|
||||
import DeviceSettings from './device-settings';
|
||||
import helpers, {BASEDRIVER_VER} from './helpers';
|
||||
@@ -30,6 +34,9 @@ const NEW_COMMAND_TIMEOUT_MS = 60 * 1000;
|
||||
|
||||
const ON_UNEXPECTED_SHUTDOWN_EVENT = 'onUnexpectedShutdown';
|
||||
|
||||
const ALL_DRIVERS_MATCH = '*';
|
||||
const FEATURE_NAME_SEPARATOR = ':';
|
||||
|
||||
export class DriverCore<const C extends Constraints, Settings extends StringRecord = StringRecord>
|
||||
implements Core<C, Settings>
|
||||
{
|
||||
@@ -258,13 +265,37 @@ export class DriverCore<const C extends Constraints, Settings extends StringReco
|
||||
* @param name - name of feature/command
|
||||
*/
|
||||
isFeatureEnabled(name: string): boolean {
|
||||
// automationName comparison is case-insensitive,
|
||||
// while feature name is case-sensitive
|
||||
const currentAutomationName = _.toLower(this.opts.automationName);
|
||||
|
||||
const parseFullName = (fullName: string) => {
|
||||
const separatorPos = fullName.indexOf(FEATURE_NAME_SEPARATOR);
|
||||
if (separatorPos < 0) {
|
||||
// TODO: This is for the backward compatibility with Appium 2.
|
||||
// TODO: We should bring back to raise an Error below for Appium 3.
|
||||
// throw new Error(
|
||||
// `The full feature name must include both the driver name/wildcard and the feature ` +
|
||||
// `name split by a colon, got '${fullName}' instead`
|
||||
// );
|
||||
return [ALL_DRIVERS_MATCH, fullName];
|
||||
}
|
||||
return [
|
||||
_.toLower(fullName.substring(0, separatorPos)),
|
||||
fullName.substring(separatorPos + 1)
|
||||
];
|
||||
};
|
||||
const parseFullNames = (fullNames: string[]) => fullNames.map(parseFullName);
|
||||
const matches = ([automationName, featureName]: [string, string]) =>
|
||||
[currentAutomationName, ALL_DRIVERS_MATCH].includes(automationName) && featureName === name;
|
||||
|
||||
// if we have explicitly denied this feature, return false immediately
|
||||
if (this.denyInsecure && _.includes(this.denyInsecure, name)) {
|
||||
if (!_.isEmpty(this.denyInsecure) && parseFullNames(this.denyInsecure).some(matches)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if we specifically have allowed the feature, return true
|
||||
if (this.allowInsecure && _.includes(this.allowInsecure, name)) {
|
||||
if (!_.isEmpty(this.allowInsecure) && parseFullNames(this.allowInsecure).some(matches)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -283,7 +314,7 @@ export class DriverCore<const C extends Constraints, Settings extends StringReco
|
||||
* not
|
||||
*
|
||||
* @param name - name of feature/command
|
||||
* @deprecated
|
||||
* @deprecated Use {@link assertFeatureEnabled} instead
|
||||
*/
|
||||
ensureFeatureEnabled(name: string) {
|
||||
this.assertFeatureEnabled(name);
|
||||
|
||||
@@ -144,8 +144,19 @@ export class BaseDriver<
|
||||
}
|
||||
};
|
||||
|
||||
const synchronizationKey = BaseDriver.name;
|
||||
// eslint-disable-next-line dot-notation
|
||||
const commandsQueueLen: number = this.commandsQueueGuard['queues']?.[synchronizationKey]?.length ?? 0;
|
||||
if (this.isCommandsQueueEnabled && commandsQueueLen > 0) {
|
||||
this.log.debug(
|
||||
`Scheduling the '${cmd}' command to the ${this.constructor.name} commands queue. ` +
|
||||
`${util.pluralize('queue item', commandsQueueLen, true)} ${commandsQueueLen === 1 ? 'is' : 'are'} ` +
|
||||
`already waiting for execution.`
|
||||
);
|
||||
}
|
||||
|
||||
const res = this.isCommandsQueueEnabled
|
||||
? await this.commandsQueueGuard.acquire(BaseDriver.name, runCommandPromise)
|
||||
? await this.commandsQueueGuard.acquire(synchronizationKey, runCommandPromise)
|
||||
: await runCommandPromise();
|
||||
|
||||
// log timing information about this command
|
||||
|
||||
@@ -7,15 +7,13 @@ import {Protocol} from '@appium/types';
|
||||
// server feature. Example rule:
|
||||
// {"pattern": "(.{1,150}).*", "flags": "s", "replacer": "$1"}
|
||||
// ^ cuts all log records to maximum 150 chars
|
||||
const MAX_LOG_BODY_LENGTH = 1024;
|
||||
const MJSONWP_ELEMENT_KEY = 'ELEMENT';
|
||||
const W3C_ELEMENT_KEY = util.W3C_WEB_ELEMENT_IDENTIFIER;
|
||||
const PROTOCOLS = {
|
||||
export const MAX_LOG_BODY_LENGTH = 1024;
|
||||
export const MJSONWP_ELEMENT_KEY = 'ELEMENT';
|
||||
export const W3C_ELEMENT_KEY = util.W3C_WEB_ELEMENT_IDENTIFIER;
|
||||
export const PROTOCOLS = {
|
||||
W3C: 'W3C',
|
||||
MJSONWP: 'MJSONWP',
|
||||
} as const satisfies Record<Protocol, Protocol>;
|
||||
|
||||
// Before Appium 2.0, this default value was '/wd/hub' by historical reasons.
|
||||
const DEFAULT_BASE_PATH = '';
|
||||
|
||||
export {MAX_LOG_BODY_LENGTH, MJSONWP_ELEMENT_KEY, W3C_ELEMENT_KEY, PROTOCOLS, DEFAULT_BASE_PATH};
|
||||
export const DEFAULT_BASE_PATH = '';
|
||||
|
||||
@@ -2,7 +2,7 @@ import _ from 'lodash';
|
||||
import log from './logger';
|
||||
import {errors} from '../protocol';
|
||||
export {handleIdempotency} from './idempotency';
|
||||
import {pathToRegexp} from 'path-to-regexp';
|
||||
import {match} from 'path-to-regexp';
|
||||
import {util} from '@appium/support';
|
||||
import {calcSignature} from '../helpers/session';
|
||||
|
||||
@@ -119,7 +119,7 @@ export function handleUpgrade(webSocketsMapping) {
|
||||
currentPathname = req.url ?? '';
|
||||
}
|
||||
for (const [pathname, wsServer] of _.toPairs(webSocketsMapping)) {
|
||||
if (pathToRegexp(pathname).test(currentPathname)) {
|
||||
if (match(pathname)(currentPathname)) {
|
||||
return wsServer.handleUpgrade(req, req.socket, Buffer.from(''), (ws) => {
|
||||
wsServer.emit('connection', ws, req);
|
||||
});
|
||||
|
||||
@@ -31,7 +31,6 @@ import {DEFAULT_BASE_PATH} from '../constants';
|
||||
import {fs, timing} from '@appium/support';
|
||||
|
||||
const KEEP_ALIVE_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
|
||||
const SERVER_CLOSE_TIMEOUT_MS = 5000;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -82,7 +81,7 @@ async function server(opts) {
|
||||
routeConfiguringFunction,
|
||||
port,
|
||||
hostname,
|
||||
cliArgs = {},
|
||||
cliArgs = /** @type {import('@appium/types').ServerArgs} */ ({}),
|
||||
allowCors = true,
|
||||
basePath = DEFAULT_BASE_PATH,
|
||||
extraMethodMap = {},
|
||||
@@ -104,6 +103,7 @@ async function server(opts) {
|
||||
httpServer,
|
||||
reject,
|
||||
keepAliveTimeout,
|
||||
gracefulShutdownTimeout: cliArgs.shutdownTimeout,
|
||||
});
|
||||
configureServer({
|
||||
app,
|
||||
@@ -191,7 +191,7 @@ function configureServer({
|
||||
* @param {ConfigureHttpOpts} opts
|
||||
* @returns {AppiumServer}
|
||||
*/
|
||||
function configureHttp({httpServer, reject, keepAliveTimeout}) {
|
||||
function configureHttp({httpServer, reject, keepAliveTimeout, gracefulShutdownTimeout}) {
|
||||
/**
|
||||
* @type {AppiumServer}
|
||||
*/
|
||||
@@ -201,6 +201,10 @@ function configureHttp({httpServer, reject, keepAliveTimeout}) {
|
||||
appiumServer.removeWebSocketHandler = removeWebSocketHandler;
|
||||
appiumServer.removeAllWebSocketHandlers = removeAllWebSocketHandlers;
|
||||
appiumServer.getWebSocketHandlers = getWebSocketHandlers;
|
||||
appiumServer.isSecure = function isSecure() {
|
||||
// eslint-disable-next-line dot-notation
|
||||
return Boolean(this['_spdyState']?.secure);
|
||||
};
|
||||
|
||||
// http.Server.close() only stops new connections, but we need to wait until
|
||||
// all connections are closed and the `close` event is emitted
|
||||
@@ -210,12 +214,15 @@ function configureHttp({httpServer, reject, keepAliveTimeout}) {
|
||||
log.info('Closing Appium HTTP server');
|
||||
const timer = new timing.Timer().start();
|
||||
const onTimeout = setTimeout(() => {
|
||||
log.info(
|
||||
`Not all active connections have been closed within ` +
|
||||
`${timer.getDuration().asMilliSeconds.toFixed(0)}ms. Exiting anyway.`
|
||||
);
|
||||
if (gracefulShutdownTimeout > 0) {
|
||||
log.info(
|
||||
`Not all active connections have been closed within ${gracefulShutdownTimeout}ms. ` +
|
||||
`This timeout might be customized by the --shutdown-timeout command line ` +
|
||||
`argument. Closing the server anyway.`
|
||||
);
|
||||
}
|
||||
process.exit(process.exitCode ?? 0);
|
||||
}, SERVER_CLOSE_TIMEOUT_MS);
|
||||
}, gracefulShutdownTimeout);
|
||||
httpServer.once('close', () => {
|
||||
log.info(
|
||||
`Appium HTTP server has been succesfully closed after ` +
|
||||
@@ -319,6 +326,9 @@ export {server, configureServer, normalizeBasePath};
|
||||
* @property {import('http').Server} httpServer - HTTP server instance
|
||||
* @property {(error?: any) => void} reject - Rejection function from `Promise` constructor
|
||||
* @property {number} keepAliveTimeout - Keep-alive timeout in milliseconds
|
||||
* @property {number} gracefulShutdownTimeout - For how long the server should delay its
|
||||
* shutdown before force-closing all open connections to it. Providing zero will force-close
|
||||
* the server without waiting for any connections.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,9 @@ export {STATIC_DIR} from './express/static';
|
||||
export {server, normalizeBasePath} from './express/server';
|
||||
|
||||
// jsonwp-proxy exports
|
||||
/** @deprecated The JWProxy export is deprecated. Please use WebDriverProxy instead */
|
||||
export {JWProxy} from './jsonwp-proxy/proxy';
|
||||
export {JWProxy as WebDriverProxy} from './jsonwp-proxy/proxy';
|
||||
|
||||
// jsonwp-status exports
|
||||
export {getSummaryByCode, codes as statusCodes} from './jsonwp-status/status';
|
||||
|
||||
@@ -18,7 +18,6 @@ import https from 'https';
|
||||
|
||||
const DEFAULT_LOG = logger.getLogger('WD Proxy');
|
||||
const DEFAULT_REQUEST_TIMEOUT = 240000;
|
||||
const COMPACT_ERROR_PATTERNS = [/\bECONNREFUSED\b/, /socket hang up/];
|
||||
|
||||
const {MJSONWP, W3C} = PROTOCOLS;
|
||||
|
||||
@@ -271,11 +270,7 @@ class JWProxy {
|
||||
}
|
||||
} else {
|
||||
proxyErrorMsg = `Could not proxy command to the remote server. Original error: ${e.message}`;
|
||||
if (COMPACT_ERROR_PATTERNS.some((p) => p.test(e.message))) {
|
||||
this.log.info(e.message);
|
||||
} else {
|
||||
this.log.info(e.stack);
|
||||
}
|
||||
this.log.info(e.message);
|
||||
}
|
||||
throw new errors.ProxyRequestError(proxyErrorMsg, e.response?.data, e.response?.status);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import _ from 'lodash';
|
||||
import {util} from '@appium/support';
|
||||
import {PROTOCOLS, DEFAULT_BASE_PATH} from '../constants';
|
||||
import {pathToRegexp} from 'path-to-regexp';
|
||||
import {match} from 'path-to-regexp';
|
||||
|
||||
const SET_ALERT_TEXT_PAYLOAD_PARAMS = {
|
||||
validate: (jsonObj) =>
|
||||
@@ -952,8 +952,8 @@ export function routeToCommandName(endpoint, method, basePath = DEFAULT_BASE_PAT
|
||||
possiblePathnames.push(normalizedPathname);
|
||||
const normalizedMethod = _.toUpper(method);
|
||||
for (const [routePath, routeSpec] of _.toPairs(METHOD_MAP)) {
|
||||
const routeRegexp = pathToRegexp(routePath);
|
||||
if (possiblePathnames.some((pp) => routeRegexp.test(pp))) {
|
||||
const routeMatcher = match(routePath);
|
||||
if (possiblePathnames.some((pp) => routeMatcher(pp))) {
|
||||
const commandName = routeSpec?.[normalizedMethod]?.command;
|
||||
if (commandName) {
|
||||
return commandName;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/base-driver",
|
||||
"version": "9.11.3",
|
||||
"version": "9.13.1",
|
||||
"description": "Base driver class for Appium drivers",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -44,30 +44,30 @@
|
||||
"test:types": "tsd"
|
||||
},
|
||||
"dependencies": {
|
||||
"@appium/support": "^5.1.3",
|
||||
"@appium/types": "^0.21.2",
|
||||
"@appium/support": "^6.0.0",
|
||||
"@appium/types": "^0.22.3",
|
||||
"@colors/colors": "1.6.0",
|
||||
"@types/async-lock": "1.4.2",
|
||||
"@types/bluebird": "3.5.42",
|
||||
"@types/express": "4.17.21",
|
||||
"@types/lodash": "4.17.7",
|
||||
"@types/method-override": "0.0.35",
|
||||
"@types/express": "5.0.0",
|
||||
"@types/lodash": "4.17.13",
|
||||
"@types/method-override": "3.0.0",
|
||||
"@types/serve-favicon": "2.5.7",
|
||||
"async-lock": "1.4.1",
|
||||
"asyncbox": "3.0.0",
|
||||
"axios": "1.7.3",
|
||||
"axios": "1.7.9",
|
||||
"bluebird": "3.7.2",
|
||||
"body-parser": "1.20.2",
|
||||
"express": "4.19.2",
|
||||
"body-parser": "1.20.3",
|
||||
"express": "4.21.1",
|
||||
"http-status-codes": "2.3.0",
|
||||
"lodash": "4.17.21",
|
||||
"lru-cache": "10.4.3",
|
||||
"method-override": "3.0.0",
|
||||
"morgan": "1.10.0",
|
||||
"path-to-regexp": "7.1.0",
|
||||
"path-to-regexp": "8.2.0",
|
||||
"serve-favicon": "2.5.0",
|
||||
"source-map-support": "0.5.21",
|
||||
"type-fest": "4.23.0",
|
||||
"type-fest": "4.30.0",
|
||||
"validate.js": "0.13.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
||||
@@ -46,10 +46,9 @@ describe('Websockets (e2e)', function () {
|
||||
_.keys(await baseServer.getWebSocketHandlers()).length.should.eql(1);
|
||||
await new B((resolve, reject) => {
|
||||
const client = new WebSocket(`ws://${TEST_HOST}:${port}${endpoint}`);
|
||||
client.once('connection', (ws, req) => {
|
||||
client.once('upgrade', (res) => {
|
||||
try {
|
||||
ws.should.not.be.empty;
|
||||
req.connection.remoteAddress.should.not.be.empty;
|
||||
res.statusCode.should.eql(101);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {pathToRegexp} from 'path-to-regexp';
|
||||
import {match} from 'path-to-regexp';
|
||||
|
||||
describe('middleware', function () {
|
||||
before(async function () {
|
||||
@@ -6,19 +6,19 @@ describe('middleware', function () {
|
||||
chai.should();
|
||||
});
|
||||
|
||||
describe('pathToRegexp', function () {
|
||||
describe('match', function () {
|
||||
it('should match static path pattern', function () {
|
||||
const pathname = '/ws/session/1234/appium/device/syslog';
|
||||
const url = 'ws://127.0.0.1:8000/ws/session/1234/appium/device/syslog';
|
||||
const currentPathname = new URL(url).pathname;
|
||||
pathToRegexp(pathname).test(currentPathname).should.be.true;
|
||||
match(pathname)(currentPathname).should.not.be.false;
|
||||
});
|
||||
|
||||
it('should match dynamic path pattern', function () {
|
||||
const pathname = '/ws/session/:sessionId/appium/device/syslog';
|
||||
const url = 'ws://127.0.0.1:8000/ws/session/1234/appium/device/syslog';
|
||||
const currentPathname = new URL(url).pathname;
|
||||
pathToRegexp(pathname).test(currentPathname).should.be.true;
|
||||
match(pathname)(currentPathname).should.not.be.false;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,6 +3,62 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.2.50](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.49...@appium/base-plugin@2.2.50) (2024-12-05)
|
||||
|
||||
**Note:** Version bump only for package @appium/base-plugin
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.2.49](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.48...@appium/base-plugin@2.2.49) (2024-12-02)
|
||||
|
||||
**Note:** Version bump only for package @appium/base-plugin
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.2.48](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.47...@appium/base-plugin@2.2.48) (2024-11-29)
|
||||
|
||||
**Note:** Version bump only for package @appium/base-plugin
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.2.47](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.46...@appium/base-plugin@2.2.47) (2024-10-24)
|
||||
|
||||
**Note:** Version bump only for package @appium/base-plugin
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.2.46](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.45...@appium/base-plugin@2.2.46) (2024-10-15)
|
||||
|
||||
**Note:** Version bump only for package @appium/base-plugin
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.2.45](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.44...@appium/base-plugin@2.2.45) (2024-09-26)
|
||||
|
||||
**Note:** Version bump only for package @appium/base-plugin
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.2.44](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.43...@appium/base-plugin@2.2.44) (2024-09-16)
|
||||
|
||||
**Note:** Version bump only for package @appium/base-plugin
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.2.43](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.42...@appium/base-plugin@2.2.43) (2024-08-07)
|
||||
|
||||
**Note:** Version bump only for package @appium/base-plugin
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user