mirror of
https://github.com/appium/appium.git
synced 2026-11-11 04:23:55 +08:00
Compare commits
540
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6b583a209 | ||
|
|
3016201f2a | ||
|
|
e0d5c4dfd6 | ||
|
|
779a3a048f | ||
|
|
07302ab3e9 | ||
|
|
609db021f4 | ||
|
|
213efd0fa4 | ||
|
|
d94a40af9f | ||
|
|
47638650ee | ||
|
|
bf8517a106 | ||
|
|
8d25be469b | ||
|
|
e118e453cc | ||
|
|
cf1dbe5389 | ||
|
|
f475b41785 | ||
|
|
8eb41d6fe8 | ||
|
|
0e6a33bd26 | ||
|
|
982571c894 | ||
|
|
78683d9176 | ||
|
|
f572c42921 | ||
|
|
dec148e997 | ||
|
|
e4faa6919b | ||
|
|
35034552b9 | ||
|
|
e5071fbf02 | ||
|
|
b1872b47b8 | ||
|
|
136903398e | ||
|
|
c704023790 | ||
|
|
27c22b7103 | ||
|
|
2b6bf4fa59 | ||
|
|
a740d9d8dd | ||
|
|
a97a7cde25 | ||
|
|
5fee01752f | ||
|
|
1445da48d8 | ||
|
|
7eb65eff9f | ||
|
|
987187e740 | ||
|
|
fa96e81341 | ||
|
|
c6abe8f102 | ||
|
|
f0de6b8719 | ||
|
|
939339adc1 | ||
|
|
d8d0c12cf9 | ||
|
|
389bff1173 | ||
|
|
367b28d5e3 | ||
|
|
2939478b47 | ||
|
|
d91add8000 | ||
|
|
84f9b4dbe4 | ||
|
|
e2fceea6b4 | ||
|
|
1a46d7d61e | ||
|
|
2ee7d4fe75 | ||
|
|
3b76a4bb63 | ||
|
|
39131c8c27 | ||
|
|
f9fa1d429d | ||
|
|
36caf86a1a | ||
|
|
24fd9a2813 | ||
|
|
27a4161b67 | ||
|
|
f18fc39de3 | ||
|
|
93722c05fa | ||
|
|
c4151a771c | ||
|
|
d9a30c1ace | ||
|
|
a7e19d1fc3 | ||
|
|
9129feb880 | ||
|
|
710738a987 | ||
|
|
41264445a3 | ||
|
|
1c5c48b582 | ||
|
|
fd270f2b09 | ||
|
|
8018f8b70e | ||
|
|
ea38864e95 | ||
|
|
cf79b3283a | ||
|
|
7c60cee787 | ||
|
|
bfac5ab9ec | ||
|
|
d329ecd7f7 | ||
|
|
aa85993c01 | ||
|
|
3c34ec1a04 | ||
|
|
2cd71fc45d | ||
|
|
bab02cc7c1 | ||
|
|
66b38e31ab | ||
|
|
66eeaa2791 | ||
|
|
a1fc1c0e18 | ||
|
|
ccbe297d3a | ||
|
|
101b31f35d | ||
|
|
b01bed2d2e | ||
|
|
6b9ad08246 | ||
|
|
2694d789c4 | ||
|
|
58fad654c3 | ||
|
|
0d1271f812 | ||
|
|
c79225f8cf | ||
|
|
2afd0e651c | ||
|
|
075466243d | ||
|
|
abb83bde62 | ||
|
|
eb139abf97 | ||
|
|
377011bdb3 | ||
|
|
1fc8582327 | ||
|
|
f6a96d6647 | ||
|
|
04b408aace | ||
|
|
f600982578 | ||
|
|
c8b9321667 | ||
|
|
c9b7eac365 | ||
|
|
efbf7115cc | ||
|
|
679ec8864c | ||
|
|
094daa24be | ||
|
|
9c3aaa1056 | ||
|
|
e58253033d | ||
|
|
25d922b7d3 | ||
|
|
0264775ecb | ||
|
|
f5b193ccf0 | ||
|
|
6d88f54918 | ||
|
|
95c4091b8b | ||
|
|
ecf927395d | ||
|
|
e1e228380f | ||
|
|
74170ec575 | ||
|
|
3f9a2ea18f | ||
|
|
2ef20b988b | ||
|
|
1dffc4e833 | ||
|
|
97c879cdd0 | ||
|
|
8300e115b2 | ||
|
|
ea186eae17 | ||
|
|
07466e02f7 | ||
|
|
a91f4a718b | ||
|
|
f53e443d64 | ||
|
|
fc11de2bda | ||
|
|
82343effc4 | ||
|
|
59a460949a | ||
|
|
b4dd22512c | ||
|
|
a18700fed6 | ||
|
|
2f312722d7 | ||
|
|
f5369c65a8 | ||
|
|
8c6c19982e | ||
|
|
e39017feac | ||
|
|
fd6dbe9eff | ||
|
|
c18b535d42 | ||
|
|
9045dfcefa | ||
|
|
98a1735913 | ||
|
|
3229e74d3d | ||
|
|
9c35776756 | ||
|
|
1b31db3be9 | ||
|
|
0a4b4f5a55 | ||
|
|
a085d44616 | ||
|
|
a10f558382 | ||
|
|
f61e7d57fa | ||
|
|
705710adc5 | ||
|
|
6a3d659c5a | ||
|
|
c760f02e14 | ||
|
|
e1ab96fc4e | ||
|
|
e8d31c63c4 | ||
|
|
787571d338 | ||
|
|
4849ad015d | ||
|
|
0878f3c8ce | ||
|
|
3dd0ac715a | ||
|
|
ce09eb2e7d | ||
|
|
9cc0377acf | ||
|
|
9b21b92418 | ||
|
|
c758fcaf13 | ||
|
|
63218cdac6 | ||
|
|
08493df3d1 | ||
|
|
bde5bd57f4 | ||
|
|
b5bdfdd4e4 | ||
|
|
cb4aa687a2 | ||
|
|
180f2611c1 | ||
|
|
1f3119ec1f | ||
|
|
2c0fb7a2e4 | ||
|
|
fa1e87535b | ||
|
|
79370cd307 | ||
|
|
712832ae61 | ||
|
|
6c9f7bbf6a | ||
|
|
0f0f60effd | ||
|
|
be35e0b3d1 | ||
|
|
17f84265d1 | ||
|
|
7da5477e7a | ||
|
|
49f0dc7ab1 | ||
|
|
622f1999d7 | ||
|
|
52b96394d6 | ||
|
|
abba69f23a | ||
|
|
83bfbce9cc | ||
|
|
9670d93a12 | ||
|
|
c986fbe5ac | ||
|
|
1c8735dfbe | ||
|
|
6d76b1ded6 | ||
|
|
9c1c5ba06e | ||
|
|
bbb70d3c1e | ||
|
|
6476197bff | ||
|
|
4c4e8d8911 | ||
|
|
c65e6d26f1 | ||
|
|
97af269d68 | ||
|
|
a31b82cc7b | ||
|
|
efe167f59a | ||
|
|
3efaac1e9a | ||
|
|
3d3abbdc6f | ||
|
|
862fbbb438 | ||
|
|
5484e9a4ff | ||
|
|
943866bcf3 | ||
|
|
62c7132476 | ||
|
|
dbcf4a133c | ||
|
|
4da7da0a14 | ||
|
|
8e68b3e2c9 | ||
|
|
2e465ef433 | ||
|
|
021aed1fdf | ||
|
|
a929cd6024 | ||
|
|
6e0fdfd967 | ||
|
|
18138f939d | ||
|
|
e43b9052d0 | ||
|
|
1a5d266c04 | ||
|
|
97d26a5796 | ||
|
|
20d410e108 | ||
|
|
ad562353d9 | ||
|
|
96152aef42 | ||
|
|
71ca18c565 | ||
|
|
4d45af1ef2 | ||
|
|
73a9891c24 | ||
|
|
dfe8bde687 | ||
|
|
9b0a5a4096 | ||
|
|
73abe981de | ||
|
|
e34c0dd639 | ||
|
|
c8f0ed5deb | ||
|
|
62fb60a8b5 | ||
|
|
4e9bf1944b | ||
|
|
7a8965f5c3 | ||
|
|
daa99525eb | ||
|
|
6234359ff2 | ||
|
|
24d8344927 | ||
|
|
e00cd5e7eb | ||
|
|
27d3c517d7 | ||
|
|
76e060cf75 | ||
|
|
3b8c41e3d4 | ||
|
|
0e5db551b4 | ||
|
|
e79c521fa7 | ||
|
|
1c4ce5d5ec | ||
|
|
a36736862f | ||
|
|
22b60daf75 | ||
|
|
7153d0adf8 | ||
|
|
ad13932e6e | ||
|
|
f044afd932 | ||
|
|
ac46d8ef5c | ||
|
|
dc37b2766d | ||
|
|
fe8b8eb808 | ||
|
|
aca8f72ee5 | ||
|
|
f135acadd4 | ||
|
|
4539f868fc | ||
|
|
5cd7076fd6 | ||
|
|
96254ef3b8 | ||
|
|
ed9d4aed09 | ||
|
|
a03b28a12c | ||
|
|
b649c64df5 | ||
|
|
22eed52c60 | ||
|
|
5e2006ae23 | ||
|
|
c45839f057 | ||
|
|
b31574d0ed | ||
|
|
c2b7070c53 | ||
|
|
e907832667 | ||
|
|
6e104d4ba1 | ||
|
|
41f2304e16 | ||
|
|
4ec08dbbf9 | ||
|
|
a842430634 | ||
|
|
4d3a5dc74a | ||
|
|
e6fc983d9d | ||
|
|
a2be0836da | ||
|
|
46f2160bf1 | ||
|
|
00e3d864f0 | ||
|
|
caee6b733b | ||
|
|
4d94dffa80 | ||
|
|
86c8f23a67 | ||
|
|
73b7820df5 | ||
|
|
26f8429509 | ||
|
|
ff96c9a6e1 | ||
|
|
87704de080 | ||
|
|
e20ee97139 | ||
|
|
52a620818a | ||
|
|
72b9efcb42 | ||
|
|
2f17a1a0ac | ||
|
|
87b8603329 | ||
|
|
7ab1df8e62 | ||
|
|
1412d58452 | ||
|
|
63908458c0 | ||
|
|
2c12f647e5 | ||
|
|
75682fa2e5 | ||
|
|
af16eafbb2 | ||
|
|
6cffa01c8d | ||
|
|
7abbd51c28 | ||
|
|
2b859134a8 | ||
|
|
06b5fe5019 | ||
|
|
d6a195a556 | ||
|
|
69bd198a18 | ||
|
|
3ca551ba2e | ||
|
|
f897dbaacb | ||
|
|
e83e513957 | ||
|
|
d3e8ddc35b | ||
|
|
d5092ffd30 | ||
|
|
91a9eb782a | ||
|
|
3a452888fc | ||
|
|
66ddff0a33 | ||
|
|
d7c30108d6 | ||
|
|
f628d517fe | ||
|
|
190c30b418 | ||
|
|
fa7ba639d4 | ||
|
|
1b1314cd6b | ||
|
|
36179e8795 | ||
|
|
825431b14a | ||
|
|
c745352c65 | ||
|
|
1d89e2a5f8 | ||
|
|
2dfae495ff | ||
|
|
980a121804 | ||
|
|
8fae5e69ea | ||
|
|
2d149121e1 | ||
|
|
362a2a2d4d | ||
|
|
503f0c1f18 | ||
|
|
a1095d2816 | ||
|
|
e7e26e5f57 | ||
|
|
b4c1b7be78 | ||
|
|
eee4c05844 | ||
|
|
f2e4bc7fcd | ||
|
|
5187e63e33 | ||
|
|
43a096cf1f | ||
|
|
27c39aed20 | ||
|
|
176f19beff | ||
|
|
dd0be5ec6c | ||
|
|
a7006075f8 | ||
|
|
3b728c641a | ||
|
|
367ba33deb | ||
|
|
5d260c78a2 | ||
|
|
7deb40a4a4 | ||
|
|
2c8ff15c30 | ||
|
|
405d8e9491 | ||
|
|
207761a2dc | ||
|
|
c6d9e079c3 | ||
|
|
69482ee634 | ||
|
|
2f27425ea3 | ||
|
|
61bba1e06f | ||
|
|
eda42cffff | ||
|
|
bfc57ea366 | ||
|
|
0110437610 | ||
|
|
0c966f2ce1 | ||
|
|
954ee5f621 | ||
|
|
9db2b7827d | ||
|
|
b11cb78d11 | ||
|
|
9c7e2efaaf | ||
|
|
987996cc22 | ||
|
|
5c3289a8e9 | ||
|
|
98d2497b49 | ||
|
|
579b6538f0 | ||
|
|
5dac35b3cc | ||
|
|
3c1f0fc99f | ||
|
|
f94df7feb0 | ||
|
|
fb8b9297da | ||
|
|
dcc6a00d10 | ||
|
|
4838d301f6 | ||
|
|
5f73989a17 | ||
|
|
6db6e2a5d0 | ||
|
|
3708211153 | ||
|
|
30f9ad5202 | ||
|
|
1cb5f91cce | ||
|
|
b885084dde | ||
|
|
90785783e6 | ||
|
|
358c6aaf4f | ||
|
|
09f7e6c245 | ||
|
|
0ebd0c3ccd | ||
|
|
4daaa14c29 | ||
|
|
8895ac79d7 | ||
|
|
196c38f7af | ||
|
|
edae4ac239 | ||
|
|
fec645f64a | ||
|
|
df7efe4339 | ||
|
|
7467221f64 | ||
|
|
cad140783f | ||
|
|
69e667b969 | ||
|
|
f2dcd2d32f | ||
|
|
77f9f14e48 | ||
|
|
550f134f75 | ||
|
|
2cc5c59426 | ||
|
|
ee57552181 | ||
|
|
7b908ec869 | ||
|
|
8f13721110 | ||
|
|
b6b340225c | ||
|
|
df60c91482 | ||
|
|
9b0dac0b61 | ||
|
|
5cd25c1d0c | ||
|
|
bfa5debfb8 | ||
|
|
6f78e06c34 | ||
|
|
d59a7c9d49 | ||
|
|
bce5946755 | ||
|
|
94e811d284 | ||
|
|
500ce8bc03 | ||
|
|
d734b4c200 | ||
|
|
666c92cd72 | ||
|
|
906ad62e8a | ||
|
|
951e1c2a3b | ||
|
|
9f5faf5bed | ||
|
|
453a9e9e01 | ||
|
|
5bb75c0859 | ||
|
|
bcda0bec56 | ||
|
|
0caab1fa58 | ||
|
|
f54961a655 | ||
|
|
8c9e66a70f | ||
|
|
46fe54555c | ||
|
|
761bee667b | ||
|
|
77eed7d4c0 | ||
|
|
8ce7b05325 | ||
|
|
5ed44a0131 | ||
|
|
55e61cc625 | ||
|
|
a1c5c03e8c | ||
|
|
5259e27ee8 | ||
|
|
2a49c53ce6 | ||
|
|
6e8c19c83e | ||
|
|
2611459ac8 | ||
|
|
1707cc1f85 | ||
|
|
9ea601c833 | ||
|
|
0515ae5c49 | ||
|
|
d0df4fbd3b | ||
|
|
5da1e7dee3 | ||
|
|
f7e6da2bd4 | ||
|
|
12347b5323 | ||
|
|
2d97841834 | ||
|
|
51e9b06784 | ||
|
|
b7eec0a01d | ||
|
|
e9eed8de4c | ||
|
|
d1e07b55e2 | ||
|
|
ecaa49f00c | ||
|
|
a570aa4781 | ||
|
|
a938fa4e7b | ||
|
|
18355bdf3a | ||
|
|
df509693d1 | ||
|
|
4048e1bfde | ||
|
|
844e80c19c | ||
|
|
e33ad95851 | ||
|
|
d308390db7 | ||
|
|
8b3c69f03c | ||
|
|
94e58f2ea6 | ||
|
|
2615935939 | ||
|
|
07b573df27 | ||
|
|
eb0aaa2e5f | ||
|
|
f736bce4a5 | ||
|
|
7343ec8cb5 | ||
|
|
2cfc5d3956 | ||
|
|
7b139d7e35 | ||
|
|
27e7e5a4e2 | ||
|
|
36fd0af47e | ||
|
|
f4426a82dc | ||
|
|
4f860502c4 | ||
|
|
59ef8af269 | ||
|
|
6461188ba8 | ||
|
|
971c584a17 | ||
|
|
4d8dec1c91 | ||
|
|
eb344f0225 | ||
|
|
3cdacfcdbe | ||
|
|
d43f749fc7 | ||
|
|
5a736fba08 | ||
|
|
7c99e88fcf | ||
|
|
75ae6145c2 | ||
|
|
31f4f298e1 | ||
|
|
b013a548f0 | ||
|
|
c5053e2248 | ||
|
|
0e84047ab3 | ||
|
|
e9255d8b8e | ||
|
|
98214795fe | ||
|
|
3c70437da4 | ||
|
|
f7b20335ea | ||
|
|
8b9597b0e5 | ||
|
|
556e90be7e | ||
|
|
ab8ee41e79 | ||
|
|
028a4274e1 | ||
|
|
9a4e5c77ac | ||
|
|
cafb9bf089 | ||
|
|
cdfe8ddc48 | ||
|
|
5ff00a0a5c | ||
|
|
fec5f3a377 | ||
|
|
5e5b76cf6b | ||
|
|
efd13358cc | ||
|
|
17eb3cac86 | ||
|
|
4419664ffd | ||
|
|
4be29e49b5 | ||
|
|
f115ebed49 | ||
|
|
beb9da3320 | ||
|
|
7c9d1363a9 | ||
|
|
5e28714442 | ||
|
|
14507371f7 | ||
|
|
384afc77ff | ||
|
|
77c9b58989 | ||
|
|
9500bd17e3 | ||
|
|
1f9e786df2 | ||
|
|
a605032f2d | ||
|
|
bfa33c6bf7 | ||
|
|
99d663c930 | ||
|
|
70b383deaa | ||
|
|
43002e3286 | ||
|
|
2f949e581e | ||
|
|
27419248e4 | ||
|
|
a5bee22a07 | ||
|
|
cfaaf768a5 | ||
|
|
0508626518 | ||
|
|
9dc0030fb9 | ||
|
|
002f8fce7f | ||
|
|
57ae03f899 | ||
|
|
df5a7da467 | ||
|
|
8de688f020 | ||
|
|
d4fcd81aed | ||
|
|
aa90b9a840 | ||
|
|
1f6c82ce6d | ||
|
|
529aeb48f1 | ||
|
|
04d9520f76 | ||
|
|
6098bdeb92 | ||
|
|
a6c4fad26b | ||
|
|
8e36bfe56d | ||
|
|
fdb95389b1 | ||
|
|
30adda0092 | ||
|
|
441c4e5572 | ||
|
|
7235392585 | ||
|
|
ce91686852 | ||
|
|
cbf7e4dfd6 | ||
|
|
a9a66d7cf5 | ||
|
|
2bd2bb7667 | ||
|
|
56a45a5244 | ||
|
|
d9e4437c55 | ||
|
|
e9a6e5425c | ||
|
|
053a88bac1 | ||
|
|
cae84898d5 | ||
|
|
dcfaa88830 | ||
|
|
1143896b97 | ||
|
|
a90797683c | ||
|
|
cc42206b4d | ||
|
|
e9ca1f5dd1 | ||
|
|
a5ba1c5efb | ||
|
|
b0b219aa01 | ||
|
|
204a07f5a4 | ||
|
|
aeef6afb8b | ||
|
|
8093c2658c | ||
|
|
5b74a7653c | ||
|
|
671c37a89c | ||
|
|
cb2d6eef6c | ||
|
|
183a2683b6 | ||
|
|
ee3d935899 | ||
|
|
591e678e6f | ||
|
|
0cc3acf5e3 | ||
|
|
b20d36f979 | ||
|
|
146bc98876 | ||
|
|
477b837b1c | ||
|
|
ac78fedf43 | ||
|
|
b0e12852f0 | ||
|
|
274b28cb29 | ||
|
|
cb9324cda4 | ||
|
|
a4b47c02c6 | ||
|
|
adf90ee746 | ||
|
|
653b95965a | ||
|
|
18864bfcac | ||
|
|
6ae5930346 |
@@ -29,8 +29,6 @@ targets:
|
||||
path: ./packages/fake-driver
|
||||
- type: npm
|
||||
path: ./packages/support
|
||||
- type: npm
|
||||
path: ./packages/test-support
|
||||
- type: npm
|
||||
path: ./packages/types
|
||||
- type: npm
|
||||
|
||||
@@ -20,12 +20,12 @@ runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Use Node.js ${{ inputs.node-version }}
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version: ${{ inputs.node-version }}
|
||||
cache: npm
|
||||
- name: SocketDev Security Check
|
||||
uses: SocketDev/action@v1
|
||||
uses: SocketDev/action@v1.3.2
|
||||
with:
|
||||
mode: firewall-free
|
||||
- name: Install dependencies
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# Copilot Instructions
|
||||
|
||||
## Code Review
|
||||
|
||||
When reviewing JavaScript or TypeScript changes, check new uses of Node.js built-in APIs against the supported Node.js versions declared in package.json#engines.node. The current supported range is ^20.19.0 || ^22.12.0 || >=24.0.0.
|
||||
|
||||
For each new Node.js built-in API or option, verify that it exists and is stable across all supported Node.js versions. If any supported version lacks the API, only supports it experimentally, or has different behavior, leave a review comment and suggest using the existing dependency, adding a fallback, avoiding the API, or raising the engine requirement.
|
||||
|
||||
Example: util.styleText exists in Node.js 20.12+, but only became stable in Node.js 22.13.0 and 23.5.0. Because this repository supports Node.js 20.19.0 and 22.12.0, replacing a color library with util.styleText should be flagged unless the project explicitly accepts relying on a non-stable API for those supported versions.
|
||||
@@ -128,11 +128,6 @@ labels:
|
||||
matcher:
|
||||
files: ['packages/strongbox/**']
|
||||
|
||||
- label: '@appium/test-support'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/test-support/**']
|
||||
|
||||
- label: '@appium/tsconfig'
|
||||
sync: true
|
||||
matcher:
|
||||
|
||||
@@ -13,4 +13,4 @@ jobs:
|
||||
name: Auto-Label PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: fuxingloh/multi-labeler@v4
|
||||
- uses: fuxingloh/multi-labeler@v5.0.0
|
||||
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
# this list of paths could potentially impact the build
|
||||
paths:
|
||||
- '**/tsconfig*.json'
|
||||
- 'packages/base-driver/static/**/*'
|
||||
- 'packages/base-driver/test-fixtures/**/*'
|
||||
- 'packages/*/test/**'
|
||||
- 'packages/*/bin'
|
||||
- 'packages/**/*.ts'
|
||||
@@ -26,7 +26,7 @@ on:
|
||||
- master
|
||||
paths:
|
||||
- '**/tsconfig*.json'
|
||||
- 'packages/base-driver/static/**/*'
|
||||
- 'packages/base-driver/test-fixtures/**/*'
|
||||
- 'packages/*/test/**'
|
||||
- 'packages/*/bin'
|
||||
- 'packages/**/*.ts'
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
outputs:
|
||||
packages: ${{ steps.discover-packages.outputs.packages }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v6.0.3
|
||||
- name: Discover packages with e2e tests
|
||||
id: discover-packages
|
||||
run: |
|
||||
@@ -110,7 +110,7 @@ jobs:
|
||||
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v6.0.3
|
||||
- name: Setup, install and build
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
@@ -129,7 +129,7 @@ jobs:
|
||||
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v6.0.3
|
||||
- name: Setup, install and build
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
@@ -148,7 +148,7 @@ jobs:
|
||||
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v6.0.3
|
||||
- name: Setup, install and build
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
@@ -171,7 +171,7 @@ jobs:
|
||||
package_dir: ${{ fromJSON(needs.prepare_e2e_packages.outputs.packages) }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v6.0.3
|
||||
- name: Setup, install and build
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
@@ -188,7 +188,7 @@ jobs:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v6.0.3
|
||||
- name: Setup and install (no build)
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
@@ -197,3 +197,5 @@ jobs:
|
||||
run-build: 'false'
|
||||
- name: ESLint
|
||||
run: npm run lint:ci
|
||||
- name: Prettier
|
||||
run: npm run format:check
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v6.0.3
|
||||
|
||||
- name: Cleanup
|
||||
run: |
|
||||
|
||||
@@ -21,9 +21,9 @@ jobs:
|
||||
project_name: appium-inspector
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v6.0.3
|
||||
- name: Use Node.js LTS
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'npm'
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
CROWDIN_PROJECT_ID: ${{ vars[matrix.project_id_var] }}
|
||||
CROWDIN_TOKEN: ${{ secrets.CROWDIN_DOCS_TOKEN }}
|
||||
- name: Post to Slack for ${{ matrix.project_name }}
|
||||
uses: slackapi/slack-github-action@v2.1.1
|
||||
uses: slackapi/slack-github-action@v3.0.3
|
||||
with:
|
||||
errors: true
|
||||
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
|
||||
@@ -12,11 +12,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v6.0.3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Use Node.js LTS
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'npm'
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
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.9
|
||||
uses: peter-evans/create-pull-request@v8.1.1
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
commit-message: 'docs(appium): Update documentation translations'
|
||||
|
||||
@@ -15,9 +15,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v6.0.3
|
||||
- name: Use Node.js LTS
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'npm'
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
steps:
|
||||
- name: Select all current LTS versions of Node.js
|
||||
id: generate-matrix
|
||||
uses: msimerson/node-lts-versions@v1
|
||||
uses: msimerson/node-lts-versions@v2.0.2
|
||||
|
||||
check:
|
||||
needs:
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Install Appium
|
||||
|
||||
@@ -37,9 +37,9 @@ jobs:
|
||||
name: Docs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v6.0.3
|
||||
- name: Install dependencies (Node.js)
|
||||
uses: bahmutov/npm-install@v1
|
||||
uses: bahmutov/npm-install@v1.12.1
|
||||
with:
|
||||
useRollingCache: true
|
||||
install-command: npm ci
|
||||
|
||||
@@ -13,11 +13,11 @@ jobs:
|
||||
env:
|
||||
FOSSA_API_KEY: ${{secrets.FOSSA_API_KEY}}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v6.0.3
|
||||
with:
|
||||
ref: master
|
||||
- name: Install dependencies
|
||||
uses: bahmutov/npm-install@v1
|
||||
uses: bahmutov/npm-install@v1.12.1
|
||||
- name: Install fossa-cli
|
||||
run: |
|
||||
curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install-latest.sh | bash
|
||||
|
||||
@@ -14,9 +14,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v6.0.3
|
||||
- name: Use Node.js LTS
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version: lts/*
|
||||
cache: 'npm'
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
# GITHUB_TOKEN is optional - if not provided, uses unauthenticated requests (rate limited)
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Post to Slack
|
||||
uses: slackapi/slack-github-action@v2.1.1
|
||||
uses: slackapi/slack-github-action@v3.0.3
|
||||
with:
|
||||
errors: true
|
||||
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
name: Appium Server Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
description: 'Dry run (no publishing or tagging)'
|
||||
required: true
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
issues: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/master' && contains(fromJSON('["mykola-mokhnach", "jlipps", "eglitise", "KazuCocoa"]'), github.actor)
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6.0.3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure git user
|
||||
run: |
|
||||
git config user.name "github-actions"
|
||||
git config user.email "github-actions@github.com"
|
||||
|
||||
- name: Setup Node and install deps (LTS)
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
node-version: lts/*
|
||||
install-command: npm ci
|
||||
run-build: 'true'
|
||||
|
||||
- name: Run Lerna publish
|
||||
env:
|
||||
# for lerna createRelease
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
DRY_RUN: ${{ inputs.dry_run }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "Running lerna publish in dry-run mode"
|
||||
printf "n\n" | npx lerna version --exact --no-git-tag-version --no-push
|
||||
else
|
||||
echo "Running lerna publish for real"
|
||||
set +e
|
||||
release_output="$(npm run release -- --yes 2>&1)"
|
||||
release_exit_code=$?
|
||||
set -e
|
||||
printf '%s\n' "$release_output"
|
||||
|
||||
if [ $release_exit_code -eq 0 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$release_output" == *"fatal: tag '"*"' already exists"* ]]; then
|
||||
existing_tag="$(printf '%s\n' "$release_output" | sed -n "s/.*fatal: tag '\\([^']*\\)' already exists.*/\\1/p" | head -n 1)"
|
||||
if [ -z "$existing_tag" ]; then
|
||||
echo "Detected existing tag failure, but could not parse tag name"
|
||||
exit $release_exit_code
|
||||
fi
|
||||
|
||||
echo "Detected existing tag failure for ${existing_tag}; attempting scoped publish recovery from tagged commit"
|
||||
git fetch --tags --force origin
|
||||
tagged_commit="$(git rev-list -n 1 "$existing_tag")"
|
||||
if [ -z "$tagged_commit" ]; then
|
||||
echo "Tag ${existing_tag} was not found after fetching tags"
|
||||
exit $release_exit_code
|
||||
fi
|
||||
|
||||
git checkout "$tagged_commit"
|
||||
missing=()
|
||||
for pkg_json in packages/*/package.json; do
|
||||
if [ ! -f "$pkg_json" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$(jq -r '.private // false' "$pkg_json")" = "true" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
pkg_name="$(jq -r '.name // empty' "$pkg_json")"
|
||||
pkg_version="$(jq -r '.version // empty' "$pkg_json")"
|
||||
if [ -z "$pkg_name" ] || [ -z "$pkg_version" ]; then
|
||||
echo "Skipping malformed package manifest: $pkg_json"
|
||||
continue
|
||||
fi
|
||||
|
||||
pkg_spec="${pkg_name}@${pkg_version}"
|
||||
if ! npm view "$pkg_spec" version >/dev/null 2>&1; then
|
||||
missing+=("$pkg_spec")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#missing[@]} -gt 0 ]; then
|
||||
echo "Missing package versions on npm before scoped recovery:"
|
||||
printf ' - %s\n' "${missing[@]}"
|
||||
echo "Publishing missing packages one-by-one with scope"
|
||||
for pkg_spec in "${missing[@]}"; do
|
||||
pkg_name="${pkg_spec%@*}"
|
||||
echo "Publishing ${pkg_name}"
|
||||
set +e
|
||||
npx lerna publish from-package --yes --scope "$pkg_name"
|
||||
scoped_exit_code=$?
|
||||
set -e
|
||||
if [ $scoped_exit_code -ne 0 ]; then
|
||||
echo "Scoped publish exited non-zero for ${pkg_name}; will verify on npm"
|
||||
fi
|
||||
done
|
||||
|
||||
final_missing=()
|
||||
for pkg_spec in "${missing[@]}"; do
|
||||
if ! npm view "$pkg_spec" version >/dev/null 2>&1; then
|
||||
final_missing+=("$pkg_spec")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#final_missing[@]} -gt 0 ]; then
|
||||
echo "Recovery incomplete after scoped retries. Still missing:"
|
||||
printf ' - %s\n' "${final_missing[@]}"
|
||||
exit $release_exit_code
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "All publishable workspace package versions are present on npm; treating recovery as successful."
|
||||
else
|
||||
echo "Release failed and no known recovery condition matched"
|
||||
exit $release_exit_code
|
||||
fi
|
||||
fi
|
||||
@@ -0,0 +1,41 @@
|
||||
# This job only publishes new releases on GitHub and updates the changelog, without publishing to NPM.
|
||||
# It can be used if the standard release workflow failed and *only* published to NPM.
|
||||
|
||||
name: Appium Server Version (Without NPM Publish)
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
issues: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
version:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/master' && contains(fromJSON('["mykola-mokhnach", "jlipps", "eglitise", "KazuCocoa"]'), github.actor)
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6.0.3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure git user
|
||||
run: |
|
||||
git config user.name "github-actions"
|
||||
git config user.email "github-actions@github.com"
|
||||
|
||||
- name: Setup Node and install deps (LTS)
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
node-version: lts/*
|
||||
install-command: npm ci
|
||||
run-build: 'true'
|
||||
|
||||
- name: Run Lerna version
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: npx lerna version --exact --yes
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check for "On Hold" label
|
||||
uses: egmacke/action-check-label@v4
|
||||
uses: egmacke/action-check-label@v5
|
||||
with:
|
||||
label: On Hold
|
||||
state: absent
|
||||
|
||||
@@ -1,38 +1,32 @@
|
||||
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
|
||||
|
||||
name: Publish docs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
workflow_run:
|
||||
workflows: ["Appium Server Release"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.x]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Install dependencies (Node.js)
|
||||
uses: bahmutov/npm-install@v1
|
||||
with:
|
||||
useRollingCache: true
|
||||
install-command: npm ci
|
||||
- name: Install dependencies (Python)
|
||||
run: PIP_BREAK_SYSTEM_PACKAGES=1 pip install -r packages/docutils/requirements.txt
|
||||
- name: Publish docs
|
||||
run: |
|
||||
cd packages/appium
|
||||
npm run publish:docs
|
||||
- uses: actions/checkout@v6.0.3
|
||||
- run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
- name: Setup Node and install deps (LTS)
|
||||
uses: ./.github/actions/setup-build
|
||||
with:
|
||||
node-version: lts/*
|
||||
install-command: npm ci
|
||||
run-build: 'true'
|
||||
- name: Install dependencies (Python)
|
||||
run: npm run install-docs-deps
|
||||
- name: Fetch gh-pages
|
||||
run: |
|
||||
git fetch origin gh-pages:gh-pages || true
|
||||
- name: Publish docs
|
||||
run: |
|
||||
npm run docs:publish
|
||||
|
||||
@@ -23,8 +23,8 @@ jobs:
|
||||
name: Check Renovate Configs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v6.0.3
|
||||
- name: Validate Renovate Config
|
||||
uses: rinchsan/renovate-config-validator@v0.2.0
|
||||
uses: rinchsan/renovate-config-validator@v0.2.1
|
||||
with:
|
||||
pattern: '{.renovaterc.json,renovate/default.json}'
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
module.exports = {
|
||||
'*.(js|ts)': ['eslint --fix', 'prettier --write'],
|
||||
'appium-config-schema.js': () => [
|
||||
'npm run --workspace=./packages/schema build',
|
||||
'git add -A packages/schema/lib/appium-config.schema.json',
|
||||
'npm run --workspace=./packages/types build',
|
||||
'git add -A packages/types/lib/appium-config.ts',
|
||||
],
|
||||
'!(package|package-lock)*.json': ['prettier --write'],
|
||||
};
|
||||
@@ -9,6 +9,7 @@ package.json
|
||||
**/*.html
|
||||
**/generated/**
|
||||
# generated
|
||||
packages/schema/lib/appium-config.schema.json
|
||||
packages/types/lib/appium-config.ts
|
||||
**/*.hbs
|
||||
|
||||
|
||||
+1
-1
@@ -33,7 +33,6 @@ to driver/client documentation
|
||||
* [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)
|
||||
|
||||
@@ -42,4 +41,5 @@ The changelog links used for these modules lead to the last version of their cha
|
||||
* [doctor](https://github.com/appium/appium/blob/8daf5e123ac14c8325acf504fb33eb28e1a3dd78/packages/doctor/CHANGELOG.md) ([removal PR](https://github.com/appium/appium/pull/20805))
|
||||
* [eslint-config-appium](https://github.com/appium/appium/blob/4b3a8c2197a587ec5a2606b662e4e7667a7852cb/packages/eslint-config-appium/CHANGELOG.md) ([removal PR](https://github.com/appium/appium/pull/20856))
|
||||
* [gulp-plugins](https://github.com/appium/appium/blob/0823f0b60e40395cd1dc3b72cfa3c0092bc81302/packages/gulp-plugins/CHANGELOG.md) ([removal PR](https://github.com/appium/appium/pull/17943))
|
||||
* [test-support](https://github.com/appium/appium/blob/1a46d7d61ee49c7e82a63687c5647c42ab69513d/packages/test-support/CHANGELOG.md) ([removal PR](https://github.com/appium/appium/pull/22351))
|
||||
* [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))
|
||||
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
## Code of Conduct
|
||||
|
||||
### What is this code of conduct for?
|
||||
|
||||
Appium is a piece of technology, but **the core of the Appium community is the people in it**. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, gender identity and expression, sexual orientation, ability, physical appearance, body size, race, age, socioeconomic status, religion (or lack thereof), or other marginalized aspect of community members. We expect all members of the Appium community to abide by this Code of Conduct whenever interacting in Appium venues (pull requests, GitHub issues, 1-1 or group chat, meetups, conferences, etc...)
|
||||
|
||||
### Examples of inappropriate behavior
|
||||
|
||||
Because we come from a variety of backgrounds, we don't want to assume that everyone has the same assumptions about what is and isn't appropriate. Here are some examples of inappropriate behavior that are incompatible with our community's ethos:
|
||||
|
||||
* Spamming, trolling, intentionally disrupting conversations, or irrelevant solicitation or advertisement
|
||||
* Making demeaning or discriminatory comments
|
||||
* Making negative assumptions about someone's background, abilities, or intentions
|
||||
* Harassing or stalking individuals (online or in person)
|
||||
* Giving someone unwelcome sexual attention or making unwelcome physical contact (in the case of an IRL event)
|
||||
* Sharing sexual images or using sexually explicit language
|
||||
|
||||
In general: treat others how you would like to be treated, were you in their place. Don't be a jerk. _Do_ ask questions. _Do_ keep conflicts productively focused on technical issues. _Do_ think before you speak; remember that what is perceived as a funny witticism in your group of friends might be hurtful or reinforce hurtful stereotypes in the context of our diverse online community. _Do_ remember that we are all people, not robots, and all equally deserving of sensitivity and respect. (If and when robots join our community, let's treat them with respect too!)
|
||||
|
||||
|
||||
### What will organizers do about inappropriate behavior?
|
||||
|
||||
If we notice you doing or saying something inappropriate, an organizer will explain why it's inappropriate and ask you to stop. We won't demonize or vilify you. But please do stop the inappropriate behavior so we can get back to writing and discussing code in a safe environment. If you have philosophical disagreements about what's actually inappropriate, please take them to a separate public or private conversation with an Appium maintainer so we don't turn pull requests into an ethics debate.
|
||||
|
||||
If you keep doing unacceptable things, we'll likely ban you, report you to GitHub, or take other appropriate action.
|
||||
|
||||
### What if I see or am subject to what feels like inappropriate behavior?
|
||||
|
||||
Let us know! Please notify a community organizer as soon as possible. Full contact information is listed in the [Contact Info](#contact-info) section of this document. All communications will be kept strictly confidential, unless otherwise required by law. No issue will be considered too inconsequential or unimportant for us to have a conversation about.
|
||||
|
||||
### Contact Info
|
||||
|
||||
If you need to report an incident, please contact any of the following organizers directly:
|
||||
|
||||
* Isaac Murchie [email](mailto:isaac@saucelabs.com) [twitter](https://twitter.com/imurchie)
|
||||
* Jonathan Lipps [email](mailto:jlipps@saucelabs.com) [twitter](https://twitter.com/jlipps)
|
||||
|
||||
### Credit, License, and Attribution
|
||||
|
||||
This Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/).
|
||||
|
||||
It's inspired among other things by:
|
||||
* [Citizen Code of Conduct](http://citizencodeofconduct.org/)
|
||||
* [npmjs](https://www.npmjs.com/policies/conduct)
|
||||
* [Geek Feminism](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy)
|
||||
* [Ashe Dryden](http://www.ashedryden.com/blog/codes-of-conduct-101-faq)
|
||||
* [Model View Culture](https://modelviewculture.com/issues/events)
|
||||
* [Open Source & Feelings](http://osfeels.com/conduct).
|
||||
@@ -50,18 +50,22 @@ The current committers are (along with their primary areas(s) of ownership or ma
|
||||
|
||||
* [@dan-maor](https://github.com/Dan-Maor) - XCUITest driver and iOS internals
|
||||
* [@dor-bl](https://github.com/Dor-bl) - DotNet client
|
||||
* [@Delta456](https://github.com/Delta456) - appium-mcp, iOS support libraries
|
||||
* [@eglitise](https://github.com/eglitise) - Appium server, Inspector
|
||||
* [@harsha509](https://github.com/harsha509) - appium-ios-tuntap
|
||||
* [@jlipps](https://github.com/jlipps) - Appium server, Inspector
|
||||
* [@kazucocoa](https://github.com/KazuCocoa) - all Appium projects
|
||||
* [@laolubenson](https://github.com/laolubenson) - DotNet client
|
||||
* [@mwakizaka](https://github.com/mwakizaka) - XCUITest driver
|
||||
* [@mykola-mokhnach](https://github.com/mykola-mokhnach) - all Appium projects
|
||||
* [@navin772](https://github.com/navin772) - appium-mcp, iOS support libraries
|
||||
* [@rerorero](https://github.com/rerorero) - XCUITest/UIA2 driver
|
||||
* [@saikrishna321](https://github.com/saikrishna321) - Java client
|
||||
* [@srinivasantarget](https://github.com/SrinivasanTarget) - Java client
|
||||
* [@tomriddly](https://github.com/tomriddly) - appium-ios-device
|
||||
* [@valfirst](https://github.com/valfirst) - Java client
|
||||
|
||||
|
||||
See [Emeritus Contributors](#emeritus-contributors) below for a list of people who formerly made
|
||||
significant contributions to the project but are no longer actively committing.
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
Google Summer of Code Ideas
|
||||
=====
|
||||
|
||||
Appium is excited to participate as a [Google Summer of Code](https://summerofcode.withgoogle.com/) sponsor project. Here's a fun list of ideas that a Summer of Code student participant can use as a foundation for thinking about what to contribute to Appium!
|
||||
|
||||
|Idea|Description|
|
||||
|----|-----------|
|
||||
|Apple tvOS Support|Our users have been asking for an Appium driver for Apple tvOS apps. Is this possible? We're not entirely sure! Why not be awesome and build it?|
|
||||
|Test App revamp|Appium uses a number of poorly-designed mobile applications in its own testing. We have to use a variety of apps because we need to test that Appium can automate all the various controls and platform features that mobile vendors provide. Really what we need is one cross-platform app (or one app per platform) that exhibit all and only the features we need to test. This would be a fun project to build some mobile apps used for testing and also demoing Appium at events and in training videos, etc...|
|
||||
|Tooling and Performance|We haven't instrumented Appium with very many performance metrics, and don't really know if we're missing some low-hanging fruit in terms of performance. Maybe you can help us do that?|
|
||||
|Babel|We have a lot of repos, and they're all on a really old version of Babel. They all need to stay in sync. How can we make this situation better, and upgrade to the latest and greatest?|
|
||||
|Unity3d Driver|Historically, Appium hasn't been great at automating games. We don't have any particular support for the frameworks used to create games. Unity is a popular one, for example. What if we could write an Appium driver that talked to an embedded process in a test version of a Unity game, that allowed us to find and interact with 3d elements? It would be amazing! You can also be amazing and lead Appium into this new world.|
|
||||
|Testing the Internet of Things|Appium's architecture makes it dead simple to integrate drivers for automating new technologies. What about _really_ new technologies like IoT devices? Help to redefine the semantics of the WebDriver protocol for use with IoT, and build a driver for an IoT device to prove it out.|
|
||||
|Driver for X|Have an idea of something else Appium could automate that it doesn't already? Build a driver for it! This would involve some awesome Node.js code, plus whatever else is needed to integrate with the platform you have in mind.|
|
||||
|
||||
Hopefully this gives you some ideas of fun projects that would be substantial and long-lasting contributions to the Appium community.
|
||||
@@ -199,11 +199,11 @@ contribution of project development and leadership!
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://lambdatest.com/?utm_source=appium.io&utm_medium=organic&utm_campaign=june_25&utm_term=sk&utm_content=webpage">
|
||||
<a href="https://www.testmuai.com">
|
||||
<picture>
|
||||
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-lambdatest-dark.png" media="(prefers-color-scheme: dark)"/>
|
||||
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-lambdatest-light.png" media="(prefers-color-scheme: light)"/>
|
||||
<img src="packages/appium/docs/overrides/assets/images/sponsor-logo-lambdatest-dark.png" width="300" alt="LambdaTest"/>
|
||||
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-dark.png" media="(prefers-color-scheme: dark)"/>
|
||||
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-light.png" media="(prefers-color-scheme: light)"/>
|
||||
<img src="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-dark.png" width="300" alt="TestMu AI (formerly LambdaTest)"/>
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
+38
-21
@@ -1,24 +1,41 @@
|
||||
import tsConfig from '@appium/eslint-config-appium-ts';
|
||||
import appiumConfig from '@appium/eslint-config-appium-ts';
|
||||
import {defineConfig, globalIgnores} from 'eslint/config';
|
||||
|
||||
export default [
|
||||
...tsConfig,
|
||||
{
|
||||
...tsConfig.find(({name}) => name === 'Test Files'),
|
||||
name: 'Test Support',
|
||||
files: [
|
||||
'packages/test-support/lib/**',
|
||||
'packages/driver-test-support/lib/**',
|
||||
'packages/plugin-test-support/lib/**',
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Ignores',
|
||||
ignores: [
|
||||
'**/build-fixtures/**',
|
||||
'packages/appium/docs/**/assets/**',
|
||||
'packages/appium/docs/**/js/**',
|
||||
'packages/appium/sample-code/**',
|
||||
],
|
||||
},
|
||||
// Create a modified config subset for test support files:
|
||||
// Extract the test file related configs (Mocha plugin and custom rules),
|
||||
// then override their 'files' property (match by name — resilient to new config entries).
|
||||
const testFileConfigItems = appiumConfig.filter(
|
||||
(item) => typeof item?.name === 'string' && item.name.startsWith('Test Files'),
|
||||
);
|
||||
const testSupportFiles = [
|
||||
'packages/driver-test-support/lib/**',
|
||||
'packages/plugin-test-support/lib/**',
|
||||
];
|
||||
const testSupportConfig = testFileConfigItems.map((item) => ({...item, files: testSupportFiles}));
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
name: 'Base Config',
|
||||
extends: [appiumConfig],
|
||||
},
|
||||
{
|
||||
name: 'Test Support',
|
||||
extends: [testSupportConfig],
|
||||
},
|
||||
{
|
||||
name: 'Consistent type-only imports (all packages)',
|
||||
files: ['**/*.{ts,tsx,mtsx}'],
|
||||
rules: {
|
||||
'@typescript-eslint/consistent-type-imports': [
|
||||
'error',
|
||||
{ fixStyle: 'separate-type-imports', prefer: 'type-imports' },
|
||||
],
|
||||
},
|
||||
},
|
||||
globalIgnores([
|
||||
'**/build-fixtures/**',
|
||||
'packages/appium/docs/**/assets/**',
|
||||
'packages/appium/docs/**/js/**',
|
||||
'packages/appium/sample-code/**',
|
||||
]),
|
||||
]);
|
||||
|
||||
+2
-1
@@ -14,7 +14,8 @@
|
||||
"version": {
|
||||
"conventionalCommits": true,
|
||||
"createRelease": "github",
|
||||
"allowBranch": ["master", "appium3"]
|
||||
"allowBranch": ["master", "appium3"],
|
||||
"exact": true
|
||||
}
|
||||
},
|
||||
"ignoreChanges": ["**/test/**", "**/*.md"],
|
||||
|
||||
Generated
+4236
-21209
File diff suppressed because it is too large
Load Diff
+36
-46
@@ -47,6 +47,8 @@
|
||||
"docs:publish": "npm run -w packages/appium publish:docs",
|
||||
"doctor": "node ./scripts/doctor-stub.mjs",
|
||||
"install-docs-deps": "npm run -w packages/appium install-docs-deps",
|
||||
"format": "prettier -w ./packages ./scripts",
|
||||
"format:check": "prettier --check ./packages ./scripts",
|
||||
"lint": "eslint .",
|
||||
"lint:ci": "eslint --quiet .",
|
||||
"lint:fix": "run-s \"lint -- --fix\"",
|
||||
@@ -57,15 +59,10 @@
|
||||
"rebuild": "run-s clean build",
|
||||
"reinstall": "run-s clean clean:deps ci",
|
||||
"reinstall:angry": "npm run clean:dangerously && npm ci",
|
||||
"release": "lerna publish",
|
||||
"release": "lerna publish --exact",
|
||||
"stage-synced-pkgs": "git add -A packages/appium/README.md \"packages/*/package.json\"",
|
||||
"start": "appium",
|
||||
"sync-pkgs": "run-p sync-pkgs:*",
|
||||
"sync-pkgs:appium-readme": "sync-monorepo-packages --force --no-package-json --packages=packages/appium README.md",
|
||||
"sync-pkgs:common-fields:default": "sync-monorepo-packages --packages=\"!packages/logger\" --fields=author,license,bugs,homepage",
|
||||
"sync-pkgs:common-fields:logger": "sync-monorepo-packages --packages=\"packages/logger\" --fields=author,bugs,homepage",
|
||||
"sync-pkgs:keywords": "sync-monorepo-packages --field=keywords --packages=\"packages/*\" --packages=\"!packages/types\" --packages=\"!packages/eslint-config-appium-ts\" ",
|
||||
"sync-pkgs:license": "sync-monorepo-packages --force --no-package-json --packages=\"!packages/logger\" LICENSE",
|
||||
"sync-pkgs": "node ./scripts/sync-monorepo-packages.mjs",
|
||||
"test": "run-s test:quick",
|
||||
"test:ci": "run-s test:smoke test:unit test:types test:e2e",
|
||||
"test:e2e": "lerna run test:e2e",
|
||||
@@ -84,13 +81,11 @@
|
||||
"singleQuote": true
|
||||
},
|
||||
"devDependencies": {
|
||||
"@colors/colors": "1.6.0",
|
||||
"@eslint/js": "9.39.1",
|
||||
"@tsconfig/node20": "20.1.8",
|
||||
"@eslint/js": "10.0.1",
|
||||
"@stylistic/eslint-plugin": "5.10.0",
|
||||
"@tsconfig/node20": "20.1.9",
|
||||
"@types/argparse": "2.0.17",
|
||||
"@types/archiver": "7.0.0",
|
||||
"@types/async-lock": "1.4.2",
|
||||
"@types/base64-stream": "1.0.5",
|
||||
"@types/bluebird": "3.5.42",
|
||||
"@types/chai": "5.2.3",
|
||||
"@types/chai-as-promised": "8.0.2",
|
||||
@@ -99,62 +94,57 @@
|
||||
"@types/json-schema": "7.0.15",
|
||||
"@types/klaw": "3.0.7",
|
||||
"@types/lockfile": "1.0.4",
|
||||
"@types/lodash": "4.17.21",
|
||||
"@types/lodash": "4.17.24",
|
||||
"@types/method-override": "3.0.0",
|
||||
"@types/mocha": "10.0.10",
|
||||
"@types/morgan": "1.9.10",
|
||||
"@types/mv": "2.1.4",
|
||||
"@types/ncp": "2.0.8",
|
||||
"@types/node": "24.10.1",
|
||||
"@types/node": "24.13.2",
|
||||
"@types/plist": "3.0.5",
|
||||
"@types/pluralize": "0.0.33",
|
||||
"@types/semver": "7.7.1",
|
||||
"@types/serve-favicon": "2.5.7",
|
||||
"@types/shell-quote": "1.7.5",
|
||||
"@types/sinon": "21.0.0",
|
||||
"@types/sinon": "21.0.1",
|
||||
"@types/sinon-chai": "4.0.0",
|
||||
"@types/source-map-support": "0.5.10",
|
||||
"@types/supports-color": "8.1.3",
|
||||
"@types/teen_process": "2.0.4",
|
||||
"@types/which": "3.0.4",
|
||||
"@types/wrap-ansi": "3.0.0",
|
||||
"@types/ws": "8.18.1",
|
||||
"@types/xmldom": "0.1.34",
|
||||
"@types/yargs": "17.0.35",
|
||||
"asyncbox": "3.0.0",
|
||||
"chai": "6.2.1",
|
||||
"asyncbox": "6.3.0",
|
||||
"chai": "6.2.2",
|
||||
"chai-as-promised": "8.0.2",
|
||||
"conventional-changelog-conventionalcommits": "7.0.2",
|
||||
"cpy-cli": "6.0.0",
|
||||
"cpy-cli": "7.0.0",
|
||||
"cross-env": "10.1.0",
|
||||
"eslint": "9.39.1",
|
||||
"eslint": "10.5.0",
|
||||
"eslint-config-prettier": "10.1.8",
|
||||
"eslint-import-resolver-typescript": "4.4.4",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
"eslint-plugin-mocha": "11.2.0",
|
||||
"eslint-plugin-promise": "7.2.1",
|
||||
"eslint-import-resolver-typescript": "4.4.5",
|
||||
"eslint-plugin-import-x": "4.16.2",
|
||||
"eslint-plugin-mocha": "11.3.0",
|
||||
"eslint-plugin-n": "18.1.0",
|
||||
"eslint-plugin-promise": "7.3.0",
|
||||
"finalhandler": "2.1.1",
|
||||
"get-port": "5.1.1",
|
||||
"json-schema-to-typescript": "15.0.4",
|
||||
"lerna": "9.0.3",
|
||||
"log-symbols": "4.1.0",
|
||||
"lerna": "9.0.7",
|
||||
"midnight-smoker": "8.0.0",
|
||||
"mjpeg-consumer": "2.0.0",
|
||||
"mjpeg-server": "0.3.1",
|
||||
"mocha": "11.7.5",
|
||||
"npm-run-all2": "8.0.4",
|
||||
"prettier": "3.7.4",
|
||||
"mocha": "11.7.6",
|
||||
"npm-run-all2": "9.0.2",
|
||||
"prettier": "3.8.4",
|
||||
"rewiremock": "3.14.6",
|
||||
"rimraf": "6.1.2",
|
||||
"serve-static": "2.2.0",
|
||||
"sinon": "21.0.0",
|
||||
"sync-monorepo-packages": "1.0.2",
|
||||
"teen_process": "3.0.4",
|
||||
"rimraf": "6.1.3",
|
||||
"serve-static": "2.2.1",
|
||||
"sinon": "22.0.0",
|
||||
"sinon-chai": "4.0.1",
|
||||
"teen_process": "4.1.3",
|
||||
"ts-node": "10.9.2",
|
||||
"tsd": "0.33.0",
|
||||
"typescript": "5.9.3",
|
||||
"typescript-eslint": "8.48.1",
|
||||
"webdriverio": "9.21.0",
|
||||
"ws": "8.18.3",
|
||||
"yaml-js": "0.3.1"
|
||||
"typescript": "6.0.3",
|
||||
"typescript-eslint": "8.61.0",
|
||||
"webdriverio": "9.28.0",
|
||||
"ws": "8.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0",
|
||||
@@ -165,10 +155,10 @@
|
||||
},
|
||||
"overrides": {
|
||||
"@sidvind/better-ajv-errors": {
|
||||
"ajv": "8.17.1"
|
||||
"ajv": "8.20.0"
|
||||
},
|
||||
"ajv-formats": {
|
||||
"ajv": "8.17.1"
|
||||
"ajv": "8.20.0"
|
||||
},
|
||||
"http-cache-semantics": "4.2.0"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// @ts-check
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
require: ['ts-node/register'],
|
||||
forbidOnly: Boolean(process.env.CI),
|
||||
color: true,
|
||||
timeout: '5s',
|
||||
};
|
||||
@@ -3,6 +3,116 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [3.5.2](https://github.com/appium/appium/compare/appium@3.5.1...appium@3.5.2) (2026-06-18)
|
||||
|
||||
**Note:** Version bump only for package appium
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [3.5.1](https://github.com/appium/appium/compare/appium@3.5.0...appium@3.5.1) (2026-06-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **storage-plugin:** add fs.sanitizeName for the delete request as well ([#22362](https://github.com/appium/appium/issues/22362)) ([5fee017](https://github.com/appium/appium/commit/5fee01752f2782e96fbe64fd13520b433d4a7535))
|
||||
|
||||
|
||||
|
||||
## [3.5.0](https://github.com/appium/appium/compare/appium@3.4.2...appium@3.5.0) (2026-05-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add IPC channels per session for drivers and plugins to communicate ([#22211](https://github.com/appium/appium/issues/22211)) ([97c879c](https://github.com/appium/appium/commit/97c879cdd02e6fcccaaea45a8d1a7088bed4ae66)), closes [#22206](https://github.com/appium/appium/issues/22206)
|
||||
* **appium:** Ditch bluebird ([#22301](https://github.com/appium/appium/issues/22301)) ([abb83bd](https://github.com/appium/appium/commit/abb83bde62e8beefdd9483a276ef2aa888722245))
|
||||
* Limit the maximum count of topics per session and make it configurable ([#22279](https://github.com/appium/appium/issues/22279)) ([0264775](https://github.com/appium/appium/commit/0264775ecb8ecaca9dac2eae47784da02a653255))
|
||||
* make assignIpc internal ([#22278](https://github.com/appium/appium/issues/22278)) ([25d922b](https://github.com/appium/appium/commit/25d922b7d3062c306c1631d6f5c227600ddd226a))
|
||||
|
||||
|
||||
|
||||
## [3.4.2](https://github.com/appium/appium/compare/appium@3.4.1...appium@3.4.2) (2026-05-07)
|
||||
|
||||
**Note:** Version bump only for package appium
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [3.4.1](https://github.com/appium/appium/compare/appium@3.4.0...appium@3.4.1) (2026-05-06)
|
||||
|
||||
**Note:** Version bump only for package appium
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [3.4.0](https://github.com/appium/appium/compare/appium@3.3.1...appium@3.4.0) (2026-05-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add 3 WebDriver extension endpoints ([#22237](https://github.com/appium/appium/issues/22237)) ([787571d](https://github.com/appium/appium/commit/787571d33836c06bb1332d7bc6cc2f9800bbdd82))
|
||||
|
||||
|
||||
|
||||
## [3.3.1](https://github.com/appium/appium/compare/appium@3.3.0...appium@3.3.1) (2026-04-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **appium:** lint warnings ([#22171](https://github.com/appium/appium/issues/22171)) ([8e68b3e](https://github.com/appium/appium/commit/8e68b3e2c9c7b6238e0ffc241adbd4d9991ead7a))
|
||||
* **appium:** plugins caching per session ([#22203](https://github.com/appium/appium/issues/22203)) ([622f199](https://github.com/appium/appium/commit/622f1999d72d2f7ebc7cc279879ea0fcefe29a54))
|
||||
|
||||
|
||||
|
||||
## [3.3.0](https://github.com/appium/appium/compare/appium@3.2.2...appium@3.3.0) (2026-04-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* use exact version for dependencies in monorepo packages instead of ^ ([#22090](https://github.com/appium/appium/issues/22090)) ([86c8f23](https://github.com/appium/appium/commit/86c8f23a670d0bbc2d359a8235828606bd36e6aa))
|
||||
|
||||
|
||||
|
||||
## [3.2.2](https://github.com/appium/appium/compare/appium@3.2.1...appium@3.2.2) (2026-03-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **appium:** Exclude package.json from tsconfig ([#22052](https://github.com/appium/appium/issues/22052)) ([1d89e2a](https://github.com/appium/appium/commit/1d89e2a5f8e478f3331666d3c308427ab834471a))
|
||||
|
||||
|
||||
|
||||
## [3.2.1](https://github.com/appium/appium/compare/appium@3.2.0...appium@3.2.1) (2026-03-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **appium:** Fix CLI arguments normalization ([#21945](https://github.com/appium/appium/issues/21945)) ([9ea601c](https://github.com/appium/appium/commit/9ea601c8330d35f45f0712e41867544d925a0f6b))
|
||||
* Avoid attaching plugins to a non-existing session ([#21964](https://github.com/appium/appium/issues/21964)) ([9f5faf5](https://github.com/appium/appium/commit/9f5faf5bedffe6196742c09c6793a6450af48ac9))
|
||||
* **logger:** Make sure we always have single logger instance per process ([#21991](https://github.com/appium/appium/issues/21991)) ([4daaa14](https://github.com/appium/appium/commit/4daaa14c29bed129d329d0881a93ecdb9de77676))
|
||||
* Type imports ([#22025](https://github.com/appium/appium/issues/22025)) ([2f27425](https://github.com/appium/appium/commit/2f27425ea300ca1af1c1da6e4be68d48e7a94346))
|
||||
|
||||
|
||||
|
||||
## [3.2.0](https://github.com/appium/appium/compare/appium@3.1.2...appium@3.2.0) (2026-01-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **appium:** Add repository links to verbose extensions list ([#21813](https://github.com/appium/appium/issues/21813)) ([ce91686](https://github.com/appium/appium/commit/ce91686852b0baab5f46990f5d40db4747922924))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **appium:** appium symlink behavior across drivers/plugins installations ([#21837](https://github.com/appium/appium/issues/21837)) ([529aeb4](https://github.com/appium/appium/commit/529aeb48f10419e21555cec05835ff07bb0e2e51))
|
||||
* apply npm run lint:fix ([#21867](https://github.com/appium/appium/issues/21867)) ([5e28714](https://github.com/appium/appium/commit/5e28714442cf59ee35b085e01e82c3f5483891fd))
|
||||
* **docs:** add missing verbose flag for CLI list command ([#21814](https://github.com/appium/appium/issues/21814)) ([dcfaa88](https://github.com/appium/appium/commit/dcfaa88830f6a5c608c92f5ae72445e065261d38))
|
||||
|
||||
|
||||
|
||||
## [3.1.2](https://github.com/appium/appium/compare/appium@3.1.1...appium@3.1.2) (2025-12-04)
|
||||
|
||||
**Note:** Version bump only for package appium
|
||||
|
||||
@@ -199,11 +199,11 @@ contribution of project development and leadership!
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://lambdatest.com/?utm_source=appium.io&utm_medium=organic&utm_campaign=june_25&utm_term=sk&utm_content=webpage">
|
||||
<a href="https://www.testmuai.com">
|
||||
<picture>
|
||||
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-lambdatest-dark.png" media="(prefers-color-scheme: dark)"/>
|
||||
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-lambdatest-light.png" media="(prefers-color-scheme: light)"/>
|
||||
<img src="packages/appium/docs/overrides/assets/images/sponsor-logo-lambdatest-dark.png" width="300" alt="LambdaTest"/>
|
||||
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-dark.png" media="(prefers-color-scheme: dark)"/>
|
||||
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-light.png" media="(prefers-color-scheme: light)"/>
|
||||
<img src="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-dark.png" width="300" alt="TestMu AI (formerly LambdaTest)"/>
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -3,7 +3,9 @@ site_name: Appium Documentation
|
||||
repo_url: https://github.com/appium/appium
|
||||
repo_name: appium/appium
|
||||
edit_uri: edit/master/packages/appium/docs
|
||||
copyright: Copyright © 2012 OpenJS Foundation - <a href="#__consent">Change cookie settings</a>
|
||||
copyright: |
|
||||
<p>Copyright <a href="https://openjsf.org">OpenJS Foundation</a> and Appium contributors. All rights reserved. The <a href="https://openjsf.org">OpenJS Foundation</a> has registered trademarks and uses trademarks. For a list of trademarks of the <a href="https://openjsf.org">OpenJS Foundation</a>, please see our <a href="https://trademark-policy.openjsf.org">Trademark Policy</a> and <a href="https://trademark-list.openjsf.org">Trademark List</a>. Trademarks and logos not indicated on the <a href="https://trademark-list.openjsf.org">list of OpenJS Foundation trademarks</a> are trademarks™ or registered® trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.</p>
|
||||
<p><a href="https://openjsf.org">The OpenJS Foundation</a> | <a href="https://terms-of-use.openjsf.org">Terms of Use</a> | <a href="https://privacy-policy.openjsf.org">Privacy Policy</a> | <a href="https://bylaws.openjsf.org">Bylaws</a> | <a href="https://code-of-conduct.openjsf.org">Code of Conduct</a> | <a href="https://trademark-policy.openjsf.org">Trademark Policy</a> | <a href="https://trademark-list.openjsf.org">Trademark List</a> | <a href="https://www.linuxfoundation.org/cookies">Cookie Policy</a></p><a href="#__consent">Change cookie settings</a>
|
||||
|
||||
theme:
|
||||
logo: assets/images/appium-logo-white.png
|
||||
|
||||
@@ -10,7 +10,7 @@ maintenance, and support from companies and volunteers. As such, we welcome cont
|
||||
|
||||
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).
|
||||
participation is governed by our [Code of Conduct](https://github.com/appium/.github/blob/master/CODE_OF_CONDUCT.md).
|
||||
|
||||
## Join the Discussion Forum
|
||||
|
||||
|
||||
@@ -568,6 +568,33 @@ capability), and then to set an internal field to that value, so that it can be
|
||||
bidiProxyUrl`. Once all this is in place, Appium will proxy BiDi commands from the client straight
|
||||
to the upstream connection.
|
||||
|
||||
### Understand server-assigned driver properties and security flags
|
||||
|
||||
When your driver is running under the main Appium server, Appium assigns a small set of
|
||||
server-related properties on your driver instance when a session is created:
|
||||
|
||||
- `cliArgs`: Driver-specific configuration derived from the Appium server’s CLI flags and/or
|
||||
configuration files (for example via the `server.driver.<your-driver-name>` section). These
|
||||
options are **not** user capabilities and cannot be influenced directly by test code.
|
||||
- `server`, `serverHost`, `serverPort`, `serverPath`: Information about the HTTP server that is
|
||||
hosting your driver. These values reflect how the Appium server was started (for example the
|
||||
`--address`, `--port`, and `--base-path` flags) and are useful when your driver needs to construct
|
||||
URLs that point back to the Appium server itself (for example when setting up proxies, webhooks,
|
||||
or other callbacks).
|
||||
|
||||
`BaseDriver` and `AppiumDriver` also cooperate to expose security-related flags on your driver
|
||||
instance:
|
||||
|
||||
- `relaxedSecurityEnabled`: Indicates whether the server is running with relaxed security enabled
|
||||
(for example via `--relaxed-security`).
|
||||
- `allowInsecure`: A list of insecure features which are explicitly allowed for this driver (derived
|
||||
from server-level options like `--allow-insecure`).
|
||||
- `denyInsecure`: A list of insecure features which are explicitly disabled for this driver (derived
|
||||
from server-level options like `--deny-insecure`).
|
||||
|
||||
See [Hide behaviour behind security flags](#hide-behaviour-behind-security-flags) for how to use
|
||||
these flags in your driver (e.g. via `isFeatureEnabled` and `assertFeatureEnabled`).
|
||||
|
||||
### Extend the existing protocol with new commands
|
||||
|
||||
You may find that the existing commands don't cut it for your driver. If you want to expose
|
||||
@@ -858,3 +885,118 @@ this.onUnexpectedShutdown(handler)
|
||||
|
||||
`handler` should be a function which receives an error object (representing the reason for the
|
||||
unexpected shutdown).
|
||||
|
||||
### Send messages to plugins running on the same session
|
||||
|
||||
Appium's driver and plugin architecture means that a single driver and any number of plugins can be
|
||||
running together for a current session. The driver and plugins don't really know anything about
|
||||
each other though, which can make coordination potentially difficult. Without creating any kind of
|
||||
tight coupling between drivers or plugins, it's possible for drivers and plugins to communicate
|
||||
along a pub/sub style message bus. With Appium's IPC feature, "message" means a combination of
|
||||
"data" (the data intended to be published or received), and metadata (timestamp, the name of the
|
||||
publisher, etc...).
|
||||
|
||||
Drivers and plugins can implement an instance method called `async onIpcInit`, in which they will
|
||||
know that the IPC channel for the session is now active. At this point, they have access to the
|
||||
following methods:
|
||||
|
||||
#### `ipcSubscribe<T>(topic: string): IIpcSubscription`
|
||||
|
||||
This method allows a driver or plugin to subscribe to a topic on the IPC channel for the session.
|
||||
Topics are simply strings. To coordinate effectively, drivers or plugins would use the same topic
|
||||
string (so this would be something advertised in the driver/plugin documentation).
|
||||
|
||||
The result of this call is an `IpcSubscription` object that allows:
|
||||
- Looping through messages on the topic via an async generator
|
||||
- Hooking up an event handler for new messages
|
||||
- Getting the last message sent on the topic
|
||||
- Publishing a message to the topic
|
||||
- Unsubscribing from the topic
|
||||
|
||||
#### `IpcSubscription` object
|
||||
|
||||
Here is an example of how subscribing and use of these subscription methods might work:
|
||||
|
||||
```ts
|
||||
async onIpcInit() {
|
||||
// we know at this point in our driver/plugin lifecycle that we can use IPC methods
|
||||
type MyMessageData = {myData: string}; // let's say the message data for this channel has this shape
|
||||
|
||||
const subscription = this.ipcSubscribe<MyMessageData>('coolTopic');
|
||||
|
||||
// listen for new messages on topic
|
||||
subscription.on('message', (message) => {
|
||||
console.log(message.data); // {myData: 'something'}
|
||||
});
|
||||
|
||||
// publish data to the topic; might throw if the data is larger than configured max size, or we
|
||||
// are no longer subscribed
|
||||
await subscription.publish({myData: 'hi'});
|
||||
|
||||
// get last message sent to topic
|
||||
const {data} = subscription.getMessage() ?? {data: null};
|
||||
// data = {myData: 'hi'}
|
||||
|
||||
// unsubscribe
|
||||
subscription.unsubscribe(); // returns true if we unsubscribed and false if no subscription existed
|
||||
}
|
||||
```
|
||||
|
||||
With a subscription object, we can also iterate async over it to receive new messages:
|
||||
|
||||
```ts
|
||||
for await (const message of subscription) {
|
||||
// here we have a message and can unwrap its data
|
||||
}
|
||||
```
|
||||
|
||||
Note that the iteration will stop when the subscription ends (i.e., when `unsubscribe` is called).
|
||||
|
||||
You can also check whether the subscription is still active (if your subscribe and unsubscribe
|
||||
logic is not locally connected):
|
||||
|
||||
```ts
|
||||
if (subscription.isActive) {
|
||||
// we know we have not yet unsubscribed
|
||||
}
|
||||
```
|
||||
|
||||
If the subscription is not active, attempts to call `subscription.publish` will throw an error.
|
||||
|
||||
#### `IpcMessage` object
|
||||
|
||||
When you get a message on a topic, it has the following shape:
|
||||
|
||||
```ts
|
||||
export type IpcMessage<T> = {
|
||||
publisher: string, // the id of the publishing object (typically of the form <ClassName>@<uniqueObjectId>)
|
||||
timestampMs: number, // when the message was published, in ms since epoch
|
||||
topic: string, // the topic the message was published on
|
||||
data: T, // the arbitrary message data. Must be serializable and a valid argument to 'structuredClone()'
|
||||
};
|
||||
```
|
||||
|
||||
#### IPC Notes
|
||||
|
||||
There are some important things to keep in mind when using Appium's IPC feature:
|
||||
- IPC is only available once `onIpcInit` has been called, at the end of the `createSession` flow.
|
||||
It cannot be used statically or in `createSession` hooks
|
||||
- In sum, IPC is only for use during a session (this is also to prevent drivers/plugins from
|
||||
accessing or reading data sent on IPC channels in other sessions.)
|
||||
- The default max size of an IPC message is 1MB. This can be configured by the server-admin by
|
||||
using the `--max-ipc-data-size` arg (value is a number in bytes).
|
||||
- If a message exceeds the configured size, any call to `publish` methods will throw, so be
|
||||
sure to cover this case in your error handling.
|
||||
- The default max number of IPC topics per session is 1000. This can be configured by the
|
||||
server-admin using the `--max-ipc-topics` arg.
|
||||
- If the topic limit is reached, calls to `subscribe` or `publish` on a new topic will throw, so
|
||||
be sure to cover this case in your error handling.
|
||||
- Topic names exist within a global namespace per session. So if you don't want to clash with other
|
||||
drivers or plugins, make sure you prefix your topic names with something unique, akin to vendor
|
||||
prefixes in the WebDriver standard (for example: `fake-driver:some-topic`). We recommend the
|
||||
format `<namespace>:<topic>`.
|
||||
|
||||
To see examples of IPC in action, check out Appium's own
|
||||
[FakeDriver](https://github.com/appium/appium/blob/master/packages/fake-driver/lib/driver.ts) and
|
||||
[FakePlugin](https://github.com/appium/appium/blob/master/packages/fake-plugin/lib/plugin.ts)
|
||||
extensions, which showcase several ways of using IPC messages.
|
||||
|
||||
@@ -512,3 +512,12 @@ async onUnexpectedShutdown(driver, cause) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Send messages to the driver or other plugins running on the same session
|
||||
|
||||
Even though drivers and plugins don't know anything about each other, it's possible for them to
|
||||
send messages that other drivers or plugins can listen for, within the context of the same session,
|
||||
using an IPC channel. Given that the developer instructions for this feature are the same for
|
||||
drivers and plugins, please head over to the [IPC development docs for
|
||||
drivers](./build-drivers.md#send-messages-to-plugins-running-on-the-same-session) at the driver
|
||||
development guide.
|
||||
|
||||
@@ -30,7 +30,7 @@ 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
|
||||
will call into `lib/bootstrap/config-file.js` to load and/or search for a configuration file and in
|
||||
`package.json`.
|
||||
|
||||
!!! note
|
||||
@@ -69,7 +69,7 @@ It is more straightforward to explain how config files are validated, so we'll s
|
||||
|
||||
### Validating Config Files
|
||||
|
||||
When a config file is found (`lib/config-file.js`), it will call the `validate` function exported
|
||||
When a config file is found (`lib/bootstrap/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.
|
||||
|
||||
|
||||
@@ -19,6 +19,43 @@ Appium has a graphical client which can be used to inspect application screensho
|
||||
application hierarchy, search for elements, run Appium commands, record app interactions, and more.
|
||||
It can be very useful for Appium test development.
|
||||
|
||||
=== "Install as an Appium Plugin"
|
||||
|
||||
```bash
|
||||
appium plugin install inspector
|
||||
```
|
||||
=== "Install Standalone"
|
||||
|
||||
Download the app from the Appium Inspector repo's [GitHub Releases section](https://github.com/appium/appium-inspector/releases).
|
||||
|
||||
### [Appium MCP](https://github.com/appium/appium-mcp)
|
||||
|
||||
Appium MCP is a Model Context Protocol (MCP) server that provides mobile test development and
|
||||
automation capabilities using Appium.
|
||||
|
||||
```json title="Install This Tool"
|
||||
// Add the following to your MCP client configuration
|
||||
{
|
||||
"appium-mcp": {
|
||||
"disabled": false,
|
||||
"timeout": 100,
|
||||
"type": "stdio",
|
||||
"command": "npx",
|
||||
"args": ["appium-mcp@latest"],
|
||||
"env": {
|
||||
"ANDROID_HOME": "/path/to/android/sdk"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### [Skills](https://github.com/appium/skills)
|
||||
|
||||
A set of AI Agent skills to support Appium automation, for example:
|
||||
|
||||
- Help preparing Appium test environment from scratch, including common driver setup
|
||||
- Help preparing XCUITest driver and WebDriverAgent for real device automation
|
||||
|
||||
## Extension Tools
|
||||
|
||||
Appium driver or plugin developers can choose to include these tools in their driver/plugin:
|
||||
@@ -33,7 +70,7 @@ details needed for the driver/plugin have been set up correctly. The tool can be
|
||||
appium {driver|plugin} doctor <extension-name>
|
||||
```
|
||||
|
||||
It shows no results if the driver/plugin author did not implement Doctor support.
|
||||
It shows no results if the driver/plugin does not have such validation checks.
|
||||
|
||||
!!! note
|
||||
|
||||
@@ -44,6 +81,18 @@ It shows no results if the driver/plugin author did not implement Doctor support
|
||||
|
||||
These tools are not maintained by the Appium team:
|
||||
|
||||
### [AppClaw](https://github.com/AppiumTestDistribution/AppClaw)
|
||||
|
||||
AppClaw is a CLI-based agentic AI layer for mobile automation, powered by [Appium MCP](#appium-mcp).
|
||||
Agent instructions can be passed directly via CLI, or defined as YAML flows in either structured
|
||||
or natural language syntax.
|
||||
|
||||
Supported by: `@AppiumTestDistribution`
|
||||
|
||||
```sh title="Install This Tool"
|
||||
npm install -g appclaw
|
||||
```
|
||||
|
||||
### [Appium Installer](https://github.com/AppiumTestDistribution/appium-installer)
|
||||
|
||||
Appium Installer is a command-line tool for simplifying setups of new Appium test environments.
|
||||
@@ -55,29 +104,3 @@ Supported by: `@AppiumTestDistribution`
|
||||
```sh title="Install This Tool"
|
||||
npm install -g appium-installer
|
||||
```
|
||||
|
||||
### [Jarvis Appium](https://github.com/AppiumTestDistribution/mcp-appium)
|
||||
|
||||
Jarvis Appium is a Model Context Protocol (MCP) server that provides mobile test development and
|
||||
automation capabilities using Appium.
|
||||
|
||||
Supported by: `@AppiumTestDistribution`
|
||||
|
||||
```json title="Install This Tool"
|
||||
// Add the following to your MCP client configuration
|
||||
{
|
||||
"mcpServers": {
|
||||
"jarvis-appium": {
|
||||
"disabled": false,
|
||||
"timeout": 100,
|
||||
"type": "stdio",
|
||||
"command": "npx",
|
||||
"args": ["jarvis-appium"],
|
||||
"env": {
|
||||
"ANDROID_HOME": "/path/to/android/sdk",
|
||||
"CAPABILITIES_CONFIG": "/path/to/your/capabilities.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
title: Session Capabilities
|
||||
---
|
||||
|
||||
"Capabilities" is the name given to the set of parameters used to start an Appium session. The
|
||||
information in the set describes what sort of "capabilities" you want your session to have, for
|
||||
example, a certain mobile operating system or a certain version of a device. Capabilities are
|
||||
represented as key-value pairs, with values allowed to be any valid JSON type, including
|
||||
other objects.
|
||||
Capabilities are the core parameters used to start an Appium session. They describe various
|
||||
features that you want your session to have, for example, a certain mobile operating system or a
|
||||
certain version of a device. Capabilities are represented as key-value pairs, with values allowed
|
||||
to be any valid JSON type, including other objects. Most importantly, they cannot be changed
|
||||
during the lifecycle of the session.
|
||||
|
||||
The W3C WebDriver spec's [section on Capabilities](https://w3c.github.io/webdriver/#capabilities)
|
||||
identifies a small set of 10 standard capabilities, including the following:
|
||||
The capabilities used in Appium follow [the W3C WebDriver specification of the same name](https://w3c.github.io/webdriver/#capabilities).
|
||||
The WebDriver spec defines a small set of standard capabilities, including the following:
|
||||
|
||||
| Capability Name | Type | Description |
|
||||
|------------------|----------|------------------------------------------------|
|
||||
@@ -17,65 +17,62 @@ identifies a small set of 10 standard capabilities, including the following:
|
||||
| `browserVersion` | `string` | The specific version of the browser |
|
||||
| `platformName` | `string` | The type of platform hosting the browser |
|
||||
|
||||
While the above capabilities are commonly used by Appium drivers, they are not sufficient for
|
||||
describing Appium-specific features, such as the name of the driver to use, or the name of the app
|
||||
to launch. In order to achieve this, Appium defines its own [extension capabilities](https://w3c.github.io/webdriver/#dfn-extension-capability).
|
||||
|
||||
## Common Appium Capabilities
|
||||
|
||||
Appium understands these browser-focused capabilities, but introduces a number of additional
|
||||
capabilities. According to the WebDriver spec, any
|
||||
non-standard "extension capabilities" must include a namespace prefix (signifying the vendor
|
||||
introducing the capability), ending in a `:`. Appium's vendor prefix is
|
||||
`appium:`, and so any Appium-specific capabilities must include this prefix. Depending on which
|
||||
client you are using, the prefix may be added automatically or in conjunction with certain
|
||||
interfaces, but it is always a good practice to explicitly include it for clarity.
|
||||
According to the WebDriver spec, extension capabilities must include a namespace prefix (signifying
|
||||
the vendor introducing the capability), and the namespace must end a colon (`:`). Appium's vendor
|
||||
prefix is `appium:`, and so any Appium-specific capabilities must include this prefix. Depending on
|
||||
your Appium client, the prefix may be added automatically or in conjunction with certain interfaces,
|
||||
but it is always a good practice to explicitly include it for clarity.
|
||||
|
||||
Here is a list of all the globally-recognized Appium capabilities:
|
||||
Here are a few commonly (but not universally!) used Appium-specific capabilities:
|
||||
|
||||
!!! info
|
||||
| Capability Name | Type | Description |
|
||||
|-------------------------|----------|-----------------------------------------------------------------|
|
||||
| `appium:automationName` | `string` | The name of the Appium driver to use |
|
||||
| `appium:udid` | `string` | The unique device identifier of a particular device to automate |
|
||||
| `appium:app` | `string` | The path to an installable application |
|
||||
|
||||
Individual drivers and plugins can support other capabilities, so refer to their documentation
|
||||
for lists of specific capability names. Some drivers may also not support all of these capabilities
|
||||
All capabilities recognized by the Appium base driver (inherited by all drivers) can be found in the
|
||||
[Capabilities Reference document](../reference/session/caps.md). While this common capability set
|
||||
is fairly small, it can be greatly extended by Appium drivers and plugins, who can (and should)
|
||||
define their own capabilities. Make sure to reference their documentation to learn more about the
|
||||
capabilities they support. You can find a list of known drivers in the [Ecosystem Drivers](../ecosystem/drivers.md) document.
|
||||
|
||||
| <div style="width:12em">Capability</div> | Type | Required? | Description |
|
||||
|--------------------------------------------|-----------|-----------|----------------------------|
|
||||
| `platformName` | `string` | yes | The type of platform hosting the app or browser |
|
||||
| `appium:automationName` | `string` | yes | The name of the Appium driver to use |
|
||||
| `browserName` | `string` | no | The name of the browser to launch and automate, if the driver supports web browsers as a special case |
|
||||
| `appium:app` | `string` | no | The path to an installable application |
|
||||
| `appium:deviceName` | `string` | no | The name of a particular device to automate, e.g., `iPhone 14` (currently only actually useful for specifying iOS simulators, since in other situations it's typically recommended to use a specific device id via the `appium:udid` capability). |
|
||||
| `appium:platformVersion` | `string` | no | The version of a platform, e.g., for iOS, `16.0` |
|
||||
| `appium:newCommandTimeout` | `number` | no | The number of seconds the Appium server should wait for clients to send commands before deciding that the client has gone away and the session should shut down. `60` seconds by default. Setting it to zero disables the timer. |
|
||||
| `appium:noReset` | `boolean` | no | If true, instruct an Appium driver to avoid its usual reset logic during session start and cleanup (default `false`) |
|
||||
| `appium:fullReset` | `boolean` | no | If true, instruct an Appium driver to augment its usual reset logic with additional steps to ensure maximum environmental reproducibility (default `false`) |
|
||||
| `appium:eventTimings` | `boolean` | no | If true, instruct an Appium driver to collect [Event Timings](./event-timing.md) (default `false`) |
|
||||
| `appium:printPageSourceOnFindFailure` | `boolean` | no | If true, collect the page source and print it to the Appium log whenever a request to find an element fails (default `false`) |
|
||||
Drivers are also able to place more complex constraints on capabilities as a group. For example,
|
||||
the XCUITest driver recommends that at least one of `browserName`, `appium:app`, or `appium:bundleId`
|
||||
is included in the capabilities, otherwise it will not be able to auto-install or auto-launch any
|
||||
application. Each driver will document how it interprets these capabilities and any other
|
||||
platform-specific requirements.
|
||||
|
||||
|
||||
Some drivers place more complex constraints on capabilities as a group. For example, while the
|
||||
`appium:app` and `browserName` capabilities are listed above as optional, if you want to launch
|
||||
a session with a specific app, the XCUITest driver requires that at least one of `appium:app`,
|
||||
`browserName`, or `appium:bundleId` are included in the capabilities (otherwise it will not know
|
||||
what app to install and/or launch and will simply open a session on the home screen). Each driver
|
||||
will document how it interprets these capabilities and any other platform-specific requirements.
|
||||
The way to construct capabilities and start a session will likely differ depending on your Appium
|
||||
client. For examples of doing this in each client library, head to the [Ecosystem Clients](../ecosystem/clients.md)
|
||||
page and click through to the appropriate client documentation.
|
||||
|
||||
!!! note
|
||||
|
||||
Capabilities are like parameters used when starting a session. After the capabilities are sent
|
||||
and the session is started, they cannot be changed. If a driver supports updating aspects of
|
||||
its behaviour in the course of a session, it will provide a [Setting](./settings.md) for this
|
||||
purpose instead of, or in addition to, a capability.
|
||||
|
||||
Each Appium client has its own way of constructing capabilities and starting a session. For
|
||||
examples of doing this in each client library, head to the [Ecosystem](../ecosystem/index.md) page
|
||||
and click through to the appropriate client documentation.
|
||||
Once your capabilities are sent to the server and the session is started, they cannot be
|
||||
changed. If a driver supports updating its behaviour during a session, it will use the
|
||||
[Settings API](./settings.md) for this purpose.
|
||||
|
||||
## BiDi Protocol Support
|
||||
|
||||
Appium supports [WebDriver BiDi](https://w3c.github.io/webdriver-bidi/) protocol since base–driver 9.5.0.
|
||||
The actual behavior depends on individual drivers while the Appium and the baseーdriver support the protocol.
|
||||
Please make sure if a driver supports the protocol and what kind of commands/events it supports in the documentation.
|
||||
In addition to the standard WebDriver protocol (now known as WebDriver Classic), Appium supports the
|
||||
[WebDriver BiDi](https://w3c.github.io/webdriver-bidi/) protocol. Support for this protocol is
|
||||
opt-in, and requires the use of the standard `webSocketUrl` capability.
|
||||
|
||||
| Capability Name | Type | Description |
|
||||
|-----------------|-----------|-----------------------------------------|
|
||||
| `webSocketUrl` | `boolean` | To enable BiDi protocol in the session. |
|
||||
| Capability Name | Type | Description |
|
||||
|-----------------|-----------|--------------------------------------------------|
|
||||
| `webSocketUrl` | `boolean` | Whether BiDi protocol is enabled in the session |
|
||||
|
||||
All BiDi commands supported by the Appium base driver (inherited by all drivers) can be found in the
|
||||
[BiDi Protocol API Reference document](../reference/api/bidi.md). Similarly to WebDriver Classic
|
||||
commands, individual Appium drivers and plugins can define their own supported standard and custom
|
||||
BiDi commands, so make sure to reference their documentation.
|
||||
|
||||
## Using `appium:options` to Group Capabilities
|
||||
|
||||
@@ -118,8 +115,7 @@ creates in response to a new session request. This is through the concept of "al
|
||||
|
||||
!!! note
|
||||
|
||||
Check out the [spec itself](https://w3c.github.io/webdriver/#processing-capabilities) or
|
||||
a [summarized version](https://github.com/jlipps/simple-wd-spec#processing-capabilities) for
|
||||
Check out the [spec itself](https://w3c.github.io/webdriver/#processing-capabilities) for
|
||||
a more in-depth description of how capabilities are processed.
|
||||
|
||||
In practice, use of first-match capabilities is not necessary or recommended for use with Appium.
|
||||
|
||||
@@ -3,27 +3,27 @@ title: Appium Server Security
|
||||
---
|
||||
|
||||
The Appium team makes every effort to ensure the security of the Appium server. This is especially
|
||||
important when Appium is run in a multitenant environment, or when multiple users are running
|
||||
sessions on the same Appium server. In general, you can only safely enable all of Appium's features if
|
||||
all the following are true:
|
||||
important when Appium is run in a multi-tenant environment, or when multiple users are running
|
||||
sessions on the same Appium server. To ensure a safe environment for Appium's purposes, all of the
|
||||
following should be true:
|
||||
|
||||
- You're running your own Appium server locally or within a protected internal network
|
||||
- You're not sharing it with any untrusted parties
|
||||
- You don't expose Appium's port(s) to the wider internet
|
||||
|
||||
But because many Appium users might not be able to guarantee such a safe environment, the Appium
|
||||
team puts many features behind a security protection mechanism, which forces system admins (the
|
||||
people who are in charge of starting the Appium server) to _explicitly opt-in_ to these features.
|
||||
(Third-party driver and plugin authors can also [hide behaviour behind security
|
||||
flags](../developing/build-drivers.md).)
|
||||
But because not all Appium hosts can guarantee such a safe environment, certain insecure Appium
|
||||
features are disabled by default, and require explicit opt-in in order to enable them. Most
|
||||
importantly, this can _only_ be done by the Appium server _host_, and Appium _client_ sessions are
|
||||
not allowed to change this.
|
||||
|
||||
For security reasons, Appium client sessions can _not_ request feature enablement via capabilities.
|
||||
This is the responsibility of the server admin who configures and launches the Appium server.
|
||||
While it is possible for an Appium host to simply enable all insecure features at once, each
|
||||
feature also has a unique name, which can be used for granular control over the server state.
|
||||
|
||||
## Security Server Args
|
||||
|
||||
The [Server CLI](../reference/cli/server.md) doc outlines three relevant arguments which may be passed to
|
||||
Appium, when starting it from the command line:
|
||||
Enabling or disabling insecure features is done via [Appium server launch arguments](../reference/cli/server.md)
|
||||
or [configuration file](./config.md). The former document outlines three relevant arguments for
|
||||
achieving this:
|
||||
|
||||
|<div style="width:10em">Parameter</div>|Description|
|
||||
|---------------------------------------|-----------|
|
||||
@@ -31,36 +31,28 @@ Appium, when starting it from the command line:
|
||||
|`--allow-insecure`|Turns on _only_ specified features, except those blocked by `--deny-insecure`. Has no effect when used in combination with `--relaxed-security`|
|
||||
|`--deny-insecure`|Explicitly turns _off_ specified features, overriding `--relaxed-security` and `--allow-insecure`|
|
||||
|
||||
All of the above arguments can also be specified in the [Appium Configuration file](./config.md).
|
||||
|
||||
Features passed to `--allow-insecure`/`--deny-insecure` must be specified as a comma-separated list,
|
||||
and each feature in the list must additionally include a prefix, indicating the driver to which the
|
||||
feature should apply. The prefix can be either the driver's `automationName`, or the wildcard (`*`)
|
||||
symbol, if the feature should be applied to all drivers. The prefix and feature name are separated
|
||||
using the colon character (`:`).
|
||||
and each feature in the list must additionally include a prefix, indicating the driver to whose
|
||||
sessions the feature should apply. The prefix can be either the driver's `automationName`, or the
|
||||
wildcard (`*`) symbol, if the feature should be applied to all drivers. The prefix and feature name
|
||||
are separated using the colon character (`:`).
|
||||
|
||||
For example, `first:foo` refers to the `foo` feature for the `first` driver, whereas `*:bar` refers
|
||||
to the `bar` feature for all drivers.
|
||||
|
||||
## Insecure Features
|
||||
|
||||
Each Appium driver is responsible for its own security, and can create its own feature names. Thus,
|
||||
you should read through the documentation for a particular driver to know which feature names it
|
||||
might use. Here is an incomplete list of examples from some of Appium's official drivers:
|
||||
Almost all insecure features are defined on a per-driver or plugin basis, so make sure to read the
|
||||
documentation for a particular driver/plugin to know which feature names it might use.
|
||||
|
||||
|<div style="width:12em">Feature Name</div>|Description|Supported Extension(s)|
|
||||
|------------|-----------|-------|
|
||||
|`get_server_logs`|Allows retrieving of Appium server logs via the Webdriver log interface|IOS, XCUITest, Android, UiAutomator2, Espresso|
|
||||
|`adb_shell`|Allows execution of arbitrary shell commands via ADB, using the `mobile: shell` command|Android, UiAutomator2, Espresso|
|
||||
|`record_audio`|Allow recording of host machine audio inputs|XCUITest|
|
||||
|`execute_driver_script`| Allows sending a request that has multiple Appium commands.|Execute Driver Plugin|
|
||||
Certain insecure features are also defined on the Appium server itself. For a list of these
|
||||
features, as well as the features defined in official plugins, see
|
||||
[the Insecure Features CLI Reference](../reference/cli/insecure-features.md) doc.
|
||||
|
||||
Some insecure features operate on the server level and do not require a driver session. Enabling
|
||||
these features require using the wildcard prefix:
|
||||
!!! note
|
||||
|
||||
|<div style="width:12em">Feature Name</div>|Description|
|
||||
|------------|-----------|
|
||||
|`session_discovery`|Allows retrieving the list of active server sessions via `GET /appium/sessions`|
|
||||
If you are a driver or plugin author and want to implement insecure features of your own, check
|
||||
out the [Building Drivers documentation](../developing/build-drivers.md#understand-server-assigned-driver-properties-and-security-flags).
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ Android TV, Samsung), and more!
|
||||
</a>
|
||||
</div>
|
||||
<div class="homepageSponsor">
|
||||
<a href="https://lambdatest.com/?utm_source=appium.io&utm_medium=organic&utm_campaign=june_25&utm_term=sk&utm_content=webpage">
|
||||
<img src="assets/images/sponsor-logo-lambdatest-dark.png#only-dark" style="width: 220px;" />
|
||||
<img src="assets/images/sponsor-logo-lambdatest-light.png#only-light" style="width: 220px;" />
|
||||
<a href="https://www.testmuai.com">
|
||||
<img src="assets/images/sponsor-logo-testmuai-dark.png#only-dark" style="width: 220px;" />
|
||||
<img src="assets/images/sponsor-logo-testmuai-light.png#only-light" style="width: 220px;" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -396,6 +396,45 @@ Deletes the virtual sensor with the type identified by `:sensorType`.
|
||||
|
||||
`null`
|
||||
|
||||
## Global Privacy Control Protocol
|
||||
|
||||
The [Global Privacy Control protocol](https://www.w3.org/TR/gpc) (GPC) is an extension of the W3C
|
||||
WebDriver protocol.
|
||||
|
||||
### setGlobalPrivacyControl
|
||||
|
||||
```
|
||||
POST /session/:sessionId/privacy
|
||||
```
|
||||
|
||||
> GPC documentation: [Set Global Privacy Control](https://www.w3.org/TR/gpc/#set-global-privacy-control)
|
||||
|
||||
Sets the value of the do-not-sell-or-share preference for the current session.
|
||||
|
||||
#### Parameters
|
||||
|
||||
|Name|Description|Type|
|
||||
|--|--|--|
|
||||
|`gpc`|Whether the browser should perform do-not-sell-or-share interactions|boolean|
|
||||
|
||||
#### Response
|
||||
|
||||
`null`
|
||||
|
||||
### getGlobalPrivacyControl
|
||||
|
||||
```
|
||||
GET /session/:sessionId/privacy
|
||||
```
|
||||
|
||||
> GPC documentation: [Get Global Privacy Control](https://www.w3.org/TR/gpc/#get-global-privacy-control)
|
||||
|
||||
Retrieves the value of the do-not-sell-or-share preference for the current session.
|
||||
|
||||
#### Response
|
||||
|
||||
`boolean` - the preference value
|
||||
|
||||
## Permissions Protocol
|
||||
|
||||
The [Permissions protocol](https://www.w3.org/TR/permissions/) is an extension of the W3C WebDriver
|
||||
@@ -523,6 +562,32 @@ Retrieves the available log types that can be used to call the [`getLog`](#getlo
|
||||
|
||||
`string[]` - an array of log types
|
||||
|
||||
## Storage Access Protocol
|
||||
|
||||
The [Storage Access protocol](https://privacycg.github.io/storage-access/) is an extension of the
|
||||
W3C WebDriver protocol.
|
||||
|
||||
### setStorageAccess
|
||||
|
||||
```
|
||||
POST /session/:sessionId/storageaccess
|
||||
```
|
||||
|
||||
> Storage Access documentation: [Set Storage Access](https://privacycg.github.io/storage-access/#set-storage-access-command)
|
||||
|
||||
Sets the storage access policy of the current browsing context.
|
||||
|
||||
#### Parameters
|
||||
|
||||
|Name|Description|Type|
|
||||
|--|--|--|
|
||||
|`blocked`|Whether storage access should be blocked (`true`) or allowed (`false`)|boolean|
|
||||
|`origin`|The origin to which the policy should be applied. Must be either a valid URL, or an asterisk (`*`) if the policy should apply to all origins.|string|
|
||||
|
||||
#### Response
|
||||
|
||||
`null`
|
||||
|
||||
## Web Authentication Protocol
|
||||
|
||||
The [Web Authentication protocol](https://w3c.github.io/webauthn/) (WebAuthn) is an extension of
|
||||
|
||||
@@ -222,7 +222,7 @@ Deletes a file in the storage.
|
||||
#### Response
|
||||
|
||||
`boolean` - `true` upon successful file deletion, or `false` if the file does not exist in
|
||||
the storage
|
||||
the storage, or if the delete request is invalid.
|
||||
|
||||
### listStorageItems
|
||||
|
||||
|
||||
@@ -117,6 +117,12 @@ appium {driver|plugin} install <install-spec>
|
||||
appium driver install git://github.com/appium/appium-xcuitest-driver.git --source=git --package=appium-xcuitest-driver
|
||||
```
|
||||
|
||||
- Install a branch of XCUITest driver repository using a Git URL:
|
||||
|
||||
```
|
||||
appium driver install git://github.com/appium/appium-xcuitest-driver.git#specific-branch --source=git --package=appium-xcuitest-driver
|
||||
```
|
||||
|
||||
## `list`
|
||||
|
||||
Lists all installed extensions, plus all official extensions that are not installed.
|
||||
@@ -134,6 +140,7 @@ appium {driver|plugin} list
|
||||
|`--installed`|Only list all installed extensions|boolean|
|
||||
|`--json`|Return the result in JSON format|boolean|
|
||||
|`--updates`|List all extensions along with information on whether newer versions are available. Only supported for extensions installed via `npm`.|boolean|
|
||||
|`--verbose`|Show additional details for each extension|boolean|
|
||||
|
||||
#### Example
|
||||
|
||||
|
||||
@@ -31,5 +31,6 @@ The executable has four main subcommands: `server`, `driver`, `plugin`, and `set
|
||||
|
||||
</div>
|
||||
|
||||
Appium also recognizes several [environment variables](./env-vars.md), which may be used for
|
||||
advanced configuration.
|
||||
The Appium server also recognizes several [environment variables](./env-vars.md) and
|
||||
[insecure feature names](./insecure-features.md), though drivers and plugins can also define
|
||||
variables and features of their own.
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Insecure Features
|
||||
---
|
||||
|
||||
The Appium server implements [a security protection mechanism](../../guides/security.md) that
|
||||
allows the management of various insecure features.
|
||||
|
||||
The following features are defined on the server level and can be used even without drivers, but
|
||||
they can only be enabled using the wildcard (`*`) prefix:
|
||||
|
||||
| Feature Name | Description |
|
||||
|-------------------|-------------------------------------------------------------------------------|
|
||||
|`session_discovery`|Allows retrieving the list of active server sessions via `GET /appium/sessions`|
|
||||
|
||||
|
||||
Of course, Appium drivers and plugins are free to define additional insecure features of their own.
|
||||
The following features are defined by official plugins:
|
||||
|
||||
| Feature Name | Plugin | Description |
|
||||
|-----------------------|----------------|----------------------------------------------------------|
|
||||
|`execute_driver_script`|`execute_driver`|Allows sending a request that has multiple Appium commands|
|
||||
@@ -48,6 +48,8 @@ appium
|
||||
|`--log-no-colors`|Disable colors in the server log|boolean|`false`|
|
||||
|`--log-timestamp`|Show timestamps in the server log|boolean|`false`|
|
||||
|`--long-stacktrace`|Add long stack traces to log entries. Recommended for debugging only.|boolean|`false`|
|
||||
|`--max-ipc-data-size`|Maximum byte size of IPC message objects.|integer|`1048576` (1MB)|
|
||||
|`--max-ipc-topics`|Maximum number of IPC topics per session.|integer|`1000`|
|
||||
|`--no-perms-check`|Skip various permission checks on the server startup|boolean|`false`|
|
||||
|`--nodeconfig`|JSON configuration for registering Appium as a node with Selenium Grid 3|object||
|
||||
|`--plugin`|Plugin-specific configuration. Keys should correspond to plugin package names|object||
|
||||
|
||||
@@ -5,8 +5,8 @@ hide:
|
||||
title: Reference
|
||||
---
|
||||
|
||||
This section of the Appium documentation provides a reference to the two main interfaces within the
|
||||
Appium server: the command-line executable, and the supported API endpoints.
|
||||
This section of the Appium documentation provides a reference to the core interfaces supported within the
|
||||
Appium server:
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
@@ -16,10 +16,16 @@ Appium server: the command-line executable, and the supported API endpoints.
|
||||
|
||||
Learn how to use the Appium command-line executable
|
||||
|
||||
- :material-lan-connect: [__Session Properties__](./session/index.md)
|
||||
|
||||
---
|
||||
|
||||
See the values of global Appium session properties
|
||||
|
||||
- :material-cloud-braces: [__API Endpoints__](./api/index.md)
|
||||
|
||||
---
|
||||
|
||||
View endpoints supported by the Appium server
|
||||
View endpoints supported by the core Appium server
|
||||
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Capabilities
|
||||
---
|
||||
|
||||
The following [capabilities](../../guides/caps.md) are recognized by the Appium server/base driver,
|
||||
and are therefore supported by all drivers as well. Some capabilities are directly handled by the
|
||||
server/base driver, while others are only validated before being passed to the actual driver.
|
||||
|
||||
!!! note
|
||||
|
||||
Capabilities not listed here will _not_ be rejected by Appium: they will simply be forwarded
|
||||
directly to the active driver/plugin.
|
||||
|
||||
### Required Capabilities
|
||||
|
||||
These capabilities are used in the Appium server/base driver, and are explicitly required in all
|
||||
Appium sessions.
|
||||
|
||||
| Capability | Description | Type |
|
||||
|-------------------------|---------------------------------------------|-----------|
|
||||
| `platformName` | Type of platform hosting the app or browser | `string` |
|
||||
| `appium:automationName` | Name of the Appium driver to use | `string` |
|
||||
|
||||
### Optional Capabilities
|
||||
|
||||
These capabilities are used in the Appium server/base driver, but are optional, and may have a
|
||||
default value.
|
||||
|
||||
| <div style="width:19em">Capability</div> | Description | Type | Default |
|
||||
|--|--|--|--|
|
||||
| `webSocketUrl` | Toggle support of the WebDriver BiDi protocol | `boolean` ||
|
||||
| `appium:eventTimings` (deprecated) | Toggle collection of [Event Timings](../../guides/event-timing.md). This capability is deprecated - please use the [`getLogEvents`](../api/appium.md#getlogevents) endpoint instead. | `boolean` ||
|
||||
| `appium:newCommandTimeout` | Number of seconds the Appium server should wait for clients to send commands before stopping the session. A value of `0` disables the timeout. | `number` | `60` |
|
||||
| `appium:printPageSourceOnFindFailure` | Toggle retrieval of the the page source and its printing to the Appium log, whenever a request to find an element fails | `boolean` ||
|
||||
|
||||
### Validated Capabilities
|
||||
|
||||
These capabilities are not directly used in the Appium server/base driver, but are still subject to
|
||||
validation checks due to their relevance in other drivers. The actual handling of these
|
||||
capabilities is optional and entirely driver-dependent.
|
||||
|
||||
| Capability | Validation |
|
||||
|-----------------------------------|---------------------------------------------------------------|
|
||||
| `platformVersion` | Must be `string` |
|
||||
| `appium:app` | Must be `string`; empty values are ignored |
|
||||
| `appium:autoLaunch` (deprecated) | Must be `boolean` |
|
||||
| `appium:autoWebview` | Must be `boolean` |
|
||||
| `appium:fullReset` | Must be `boolean`; mutually exclusive with `appium:noReset` |
|
||||
| `appium:language` | Must be `string` |
|
||||
| `appium:locale` | Must be `string` |
|
||||
| `appium:orientation` | Must be either `LANDSCAPE` or `PORTRAIT` |
|
||||
| `appium:noReset` | Must be `boolean`; mutually exclusive with `appium:fullReset` |
|
||||
| `appium:udid` | Must be `string` |
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Session Properties
|
||||
---
|
||||
|
||||
An Appium session has several key properties, each with its own set of supported values:
|
||||
capabilities, execute methods, settings, locator strategies, and others. The supported values for
|
||||
each property are primarily defined by the active driver and plugins, but some properties also have
|
||||
common values provided by the Appium server and its base driver:
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- [__Capabilities__](./caps.md)
|
||||
|
||||
A small set of basic capabilities
|
||||
|
||||
- [__Command Endpoints__](../api/index.md)
|
||||
|
||||
The core set of API endpoints
|
||||
|
||||
</div>
|
||||
@@ -26,3 +26,4 @@ maintainers, Jonathan Lipps, with lots of useful guides
|
||||
- [AppiumConf 2021](https://www.youtube.com/playlist?list=PL9Z-JgiTsOYRCcJhDfmKAah9XmAp2b903)
|
||||
- [AppiumConf 2024](https://www.youtube.com/playlist?list=PL9Z-JgiTsOYQaU5i5LJtAWlh5WVZPi3If)
|
||||
- [SeleniumConf & AppiumConf 2025](https://www.youtube.com/playlist?list=PLRdSclUtJDYV2R92TLbmwxws6clruuTjH)
|
||||
- [SeleniumConf & AppiumConf 2026](https://www.youtube.com/playlist?list=PLRdSclUtJDYVgVqdKnSyBLBmFdA0KE_Dk)
|
||||
|
||||
@@ -22,6 +22,11 @@ Hub](https://opencollective.com/appium).
|
||||
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.testmuai.com">
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-testmuai-dark.png#only-dark" width="250" alt="TestMu AI (formerly LambdaTest)" />
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-testmuai-light.png#only-light" width="250" alt="TestMu AI (formerly LambdaTest)" />
|
||||
</a>
|
||||
|
||||
## Strategic Partners
|
||||
|
||||
We are very grateful for the financial and marketing support of our exclusive Strategic Partners,
|
||||
@@ -33,9 +38,9 @@ contributors!
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-browserstack-light.png#only-light" width="250" alt="BrowserStack" />
|
||||
</a>
|
||||
|
||||
<a href="https://lambdatest.com/?utm_source=appium.io&utm_medium=organic&utm_campaign=june_25&utm_term=sk&utm_content=webpage">
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-lambdatest-dark.png#only-dark" width="250" alt="LambdaTest" />
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-lambdatest-light.png#only-light" width="250" alt="LambdaTest" />
|
||||
<a href="https://www.testmuai.com">
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-testmuai-dark.png#only-dark" width="250" alt="TestMu AI (formerly LambdaTest)" />
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-testmuai-light.png#only-light" width="250" alt="TestMu AI (formerly LambdaTest)" />
|
||||
</a>
|
||||
|
||||
## Gold Sponsors
|
||||
|
||||
@@ -10,7 +10,7 @@ maintenance, and support from companies and volunteers. As such, we welcome cont
|
||||
|
||||
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).
|
||||
participation is governed by our [Code of Conduct](https://github.com/appium/.github/blob/master/CODE_OF_CONDUCT.md).
|
||||
|
||||
## Join the Discussion Forum
|
||||
|
||||
|
||||
@@ -570,6 +570,33 @@ capability), and then to set an internal field to that value, so that it can be
|
||||
bidiProxyUrl`. Once all this is in place, Appium will proxy BiDi commands from the client straight
|
||||
to the upstream connection.
|
||||
|
||||
### Understand server-assigned driver properties and security flags
|
||||
|
||||
When your driver is running under the main Appium server, Appium assigns a small set of
|
||||
server-related properties on your driver instance when a session is created:
|
||||
|
||||
- `cliArgs`: Driver-specific configuration derived from the Appium server’s CLI flags and/or
|
||||
configuration files (for example via the `server.driver.<your-driver-name>` section). These
|
||||
options are **not** user capabilities and cannot be influenced directly by test code.
|
||||
- `server`, `serverHost`, `serverPort`, `serverPath`: Information about the HTTP server that is
|
||||
hosting your driver. These values reflect how the Appium server was started (for example the
|
||||
`--address`, `--port`, and `--base-path` flags) and are useful when your driver needs to construct
|
||||
URLs that point back to the Appium server itself (for example when setting up proxies, webhooks,
|
||||
or other callbacks).
|
||||
|
||||
`BaseDriver` and `AppiumDriver` also cooperate to expose security-related flags on your driver
|
||||
instance:
|
||||
|
||||
- `relaxedSecurityEnabled`: Indicates whether the server is running with relaxed security enabled
|
||||
(for example via `--relaxed-security`).
|
||||
- `allowInsecure`: A list of insecure features which are explicitly allowed for this driver (derived
|
||||
from server-level options like `--allow-insecure`).
|
||||
- `denyInsecure`: A list of insecure features which are explicitly disabled for this driver (derived
|
||||
from server-level options like `--deny-insecure`).
|
||||
|
||||
See [Hide behaviour behind security flags](#hide-behaviour-behind-security-flags) for how to use
|
||||
these flags in your driver (e.g. via `isFeatureEnabled` and `assertFeatureEnabled`).
|
||||
|
||||
### Extend the existing protocol with new commands
|
||||
|
||||
You may find that the existing commands don't cut it for your driver. If you want to expose
|
||||
@@ -579,7 +606,7 @@ three ways:
|
||||
1. Extending the classic WebDriver protocol and creating client-side plugins to access the extensions via the classic HTTP interface
|
||||
2. Extending the WebDriver BiDi protocol with new modules and methods, accessed from a client via the BiDi interface
|
||||
3. Overloading the Execute Script command by defining Execute
|
||||
Methods
|
||||
Methods
|
||||
|
||||
If you want to follow the first path, you can direct Appium to recognize new methods and add them
|
||||
to its set of allowed HTTP routes and command names. You do this by assigning the `newMethodMap`
|
||||
@@ -685,17 +712,17 @@ async execute(script, args) {
|
||||
A couple notes about this system:
|
||||
|
||||
1. The arguments array sent via the call to Execute Script must contain only zero or one element(s). The
|
||||
first item in the list is considered to be the parameters object for your method. These parameters
|
||||
will be parsed, validated, and then applied to your overload method in the order specified in
|
||||
`executeMethodMap` (the order specified in the `required` parameters list, followed by the
|
||||
`optional` parameters list). I.e., this framework assumes only a single actual argument sent in via
|
||||
Execute Script (and this argument should be an object with keys/values representing the
|
||||
parameters your execute method expects).
|
||||
first item in the list is considered to be the parameters object for your method. These parameters
|
||||
will be parsed, validated, and then applied to your overload method in the order specified in
|
||||
`executeMethodMap` (the order specified in the `required` parameters list, followed by the
|
||||
`optional` parameters list). I.e., this framework assumes only a single actual argument sent in via
|
||||
Execute Script (and this argument should be an object with keys/values representing the
|
||||
parameters your execute method expects).
|
||||
2. Appium does not automatically implement `execute` (the Execute Script handler) for you. You may
|
||||
wish, for example, to only call the `executeMethod` helper function when you're not in proxy
|
||||
mode!
|
||||
wish, for example, to only call the `executeMethod` helper function when you're not in proxy
|
||||
mode!
|
||||
3. The `executeMethod` helper will reject with an error if a script name doesn't match one of the
|
||||
script names defined as a command in `executeMethodMap`, or if there are missing parameters.
|
||||
script names defined as a command in `executeMethodMap`, or if there are missing parameters.
|
||||
|
||||
One of the nice things about the Execute Method strategy is that methods implemented in this way
|
||||
will be available via the classic or BiDi interfaces (since they will result in the same Appium
|
||||
@@ -770,7 +797,7 @@ that multiple simultaneous sessions don't use the same resources:
|
||||
1. Have your users specify resource IDs via capabilities (`appium:driverPort` etc)
|
||||
2. Just always use free resources (find a new random port for each session)
|
||||
3. Have each driver express what resources it is using, then examine currently-used resources from
|
||||
other drivers when a new session begins.
|
||||
other drivers when a new session begins.
|
||||
|
||||
To support this third strategy, you can implement `get driverData` in your driver to return what
|
||||
sorts of resources your driver is currently using, for example:
|
||||
@@ -864,3 +891,120 @@ this.onUnexpectedShutdown(handler)
|
||||
|
||||
`handler` should be a function which receives an error object (representing the reason for the
|
||||
unexpected shutdown).
|
||||
|
||||
### Send messages to plugins running on the same session
|
||||
|
||||
Appium's driver and plugin architecture means that a single driver and any number of plugins can be
|
||||
running together for a current session. The driver and plugins don't really know anything about
|
||||
each other though, which can make coordination potentially difficult. Without creating any kind of
|
||||
tight coupling between drivers or plugins, it's possible for drivers and plugins to communicate
|
||||
along a pub/sub style message bus. With Appium's IPC feature, "message" means a combination of
|
||||
"data" (the data intended to be published or received), and metadata (timestamp, the name of the
|
||||
publisher, etc...).
|
||||
|
||||
Drivers and plugins can implement an instance method called `async onIpcInit`, in which they will
|
||||
know that the IPC channel for the session is now active. At this point, they have access to the
|
||||
following methods:
|
||||
|
||||
#### `ipcSubscribe<T>(topic: string): IIpcSubscription`
|
||||
|
||||
This method allows a driver or plugin to subscribe to a topic on the IPC channel for the session.
|
||||
Topics are simply strings. To coordinate effectively, drivers or plugins would use the same topic
|
||||
string (so this would be something advertised in the driver/plugin documentation).
|
||||
|
||||
The result of this call is an `IpcSubscription` object that allows:
|
||||
|
||||
- Looping through messages on the topic via an async generator
|
||||
- Hooking up an event handler for new messages
|
||||
- Getting the last message sent on the topic
|
||||
- Publishing a message to the topic
|
||||
- Unsubscribing from the topic
|
||||
|
||||
#### `IpcSubscription` object
|
||||
|
||||
Here is an example of how subscribing and use of these subscription methods might work:
|
||||
|
||||
```ts
|
||||
async onIpcInit() {
|
||||
// we know at this point in our driver/plugin lifecycle that we can use IPC methods
|
||||
type MyMessageData = {myData: string}; // let's say the message data for this channel has this shape
|
||||
|
||||
const subscription = this.ipcSubscribe<MyMessageData>('coolTopic');
|
||||
|
||||
// listen for new messages on topic
|
||||
subscription.on('message', (message) => {
|
||||
console.log(message.data); // {myData: 'something'}
|
||||
});
|
||||
|
||||
// publish data to the topic; might throw if the data is larger than configured max size, or we
|
||||
// are no longer subscribed
|
||||
await subscription.publish({myData: 'hi'});
|
||||
|
||||
// get last message sent to topic
|
||||
const {data} = subscription.getMessage() ?? {data: null};
|
||||
// data = {myData: 'hi'}
|
||||
|
||||
// unsubscribe
|
||||
subscription.unsubscribe(); // returns true if we unsubscribed and false if no subscription existed
|
||||
}
|
||||
```
|
||||
|
||||
With a subscription object, we can also iterate async over it to receive new messages:
|
||||
|
||||
```ts
|
||||
for await (const message of subscription) {
|
||||
// here we have a message and can unwrap its data
|
||||
}
|
||||
```
|
||||
|
||||
Note that the iteration will stop when the subscription ends (i.e., when `unsubscribe` is called).
|
||||
|
||||
You can also check whether the subscription is still active (if your subscribe and unsubscribe
|
||||
logic is not locally connected):
|
||||
|
||||
```ts
|
||||
if (subscription.isActive) {
|
||||
// we know we have not yet unsubscribed
|
||||
}
|
||||
```
|
||||
|
||||
If the subscription is not active, attempts to call `subscription.publish` will throw an error.
|
||||
|
||||
#### `IpcMessage` object
|
||||
|
||||
When you get a message on a topic, it has the following shape:
|
||||
|
||||
```ts
|
||||
export type IpcMessage<T> = {
|
||||
publisher: string, // the id of the publishing object (typically of the form <ClassName>@<uniqueObjectId>)
|
||||
timestampMs: number, // when the message was published, in ms since epoch
|
||||
topic: string, // the topic the message was published on
|
||||
data: T, // the arbitrary message data. Must be serializable and a valid argument to 'structuredClone()'
|
||||
};
|
||||
```
|
||||
|
||||
#### IPC Notes
|
||||
|
||||
There are some important things to keep in mind when using Appium's IPC feature:
|
||||
|
||||
- IPC is only available once `onIpcInit` has been called, at the end of the `createSession` flow.
|
||||
It cannot be used statically or in `createSession` hooks
|
||||
- In sum, IPC is only for use during a session (this is also to prevent drivers/plugins from
|
||||
accessing or reading data sent on IPC channels in other sessions.)
|
||||
- The default max size of an IPC message is 1MB. This can be configured by the server-admin by
|
||||
using the `--max-ipc-data-size` arg (value is a number in bytes).
|
||||
- If a message exceeds the configured size, any call to `publish` methods will throw, so be
|
||||
sure to cover this case in your error handling.
|
||||
- The default max number of IPC topics per session is 1000. This can be configured by the
|
||||
server-admin using the `--max-ipc-topics` arg.
|
||||
- If the topic limit is reached, calls to `subscribe` or `publish` on a new topic will throw, so
|
||||
be sure to cover this case in your error handling.
|
||||
- Topic names exist within a global namespace per session. So if you don't want to clash with other
|
||||
drivers or plugins, make sure you prefix your topic names with something unique, akin to vendor
|
||||
prefixes in the WebDriver standard (for example: `fake-driver:some-topic`). We recommend the
|
||||
format `<namespace>:<topic>`.
|
||||
|
||||
To see examples of IPC in action, check out Appium's own
|
||||
[FakeDriver](https://github.com/appium/appium/blob/master/packages/fake-driver/lib/driver.ts) and
|
||||
[FakePlugin](https://github.com/appium/appium/blob/master/packages/fake-plugin/lib/plugin.ts)
|
||||
extensions, which showcase several ways of using IPC messages.
|
||||
|
||||
@@ -236,13 +236,13 @@ upstream server. In this case, we might run into a problem, because the plugin n
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
|
||||
@@ -331,7 +331,7 @@ drivers, you can create new commands in one of two ways, just as is possible for
|
||||
1. Extending the WebDriver protocol and creating client-side plugins to access the extensions
|
||||
2. Extending the WebDriver BiDi protocol with new modules and methods, accessed from a client via the BiDi interface
|
||||
3. Overloading the Execute Script command by defining Execute
|
||||
Methods
|
||||
Methods
|
||||
|
||||
#### Extending the HTTP Protocol
|
||||
|
||||
@@ -458,10 +458,10 @@ inside the plugin class:
|
||||
|
||||
1. The `executeMethodMap`, defined in just the same way as for drivers
|
||||
2. The implementation of the command method as defined in `executeMethodMap` (in this case,
|
||||
`plugMeIn`)
|
||||
`plugMeIn`)
|
||||
3. The overriding/handling of the `execute` command. Just like any plugin command handlers, the
|
||||
first two arguments are `next` and `driver`, followed by the script name and args. `BasePlugin`
|
||||
implements a helper method which we can simply call with all of these arguments.
|
||||
first two arguments are `next` and `driver`, followed by the script name and args. `BasePlugin`
|
||||
implements a helper method which we can simply call with all of these arguments.
|
||||
|
||||
Overriding Execute Methods from drivers works as you'd expect: if your plugin defines an Execute
|
||||
Method with the same name as that of a driver, your command (in this case `plugMeIn`) will be
|
||||
@@ -518,3 +518,12 @@ async onUnexpectedShutdown(driver, cause) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Send messages to the driver or other plugins running on the same session
|
||||
|
||||
Even though drivers and plugins don't know anything about each other, it's possible for them to
|
||||
send messages that other drivers or plugins can listen for, within the context of the same session,
|
||||
using an IPC channel. Given that the developer instructions for this feature are the same for
|
||||
drivers and plugins, please head over to the IPC development docs for
|
||||
drivers at the driver
|
||||
development guide.
|
||||
|
||||
@@ -29,7 +29,7 @@ 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
|
||||
will call into `lib/bootstrap/config-file.js` to load and/or search for a configuration file and in
|
||||
`package.json`.
|
||||
|
||||
!!! note
|
||||
@@ -72,7 +72,7 @@ It is more straightforward to explain how config files are validated, so we'll s
|
||||
|
||||
### Validating Config Files
|
||||
|
||||
When a config file is found (`lib/config-file.js`), it will call the `validate` function exported
|
||||
When a config file is found (`lib/bootstrap/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.
|
||||
|
||||
|
||||
@@ -21,6 +21,48 @@ Appium has a graphical client which can be used to inspect application screensho
|
||||
application hierarchy, search for elements, run Appium commands, record app interactions, and more.
|
||||
It can be very useful for Appium test development.
|
||||
|
||||
\=== "Install as an Appium Plugin"
|
||||
|
||||
````
|
||||
```bash
|
||||
appium plugin install inspector
|
||||
```
|
||||
````
|
||||
|
||||
\=== "Install Standalone"
|
||||
|
||||
```
|
||||
Download the app from the Appium Inspector repo's [GitHub Releases section](https://github.com/appium/appium-inspector/releases).
|
||||
```
|
||||
|
||||
### [Appium MCP](https://github.com/appium/appium-mcp)
|
||||
|
||||
Appium MCP is a Model Context Protocol (MCP) server that provides mobile test development and
|
||||
automation capabilities using Appium.
|
||||
|
||||
```json title="Install This Tool"
|
||||
// Add the following to your MCP client configuration
|
||||
{
|
||||
"appium-mcp": {
|
||||
"disabled": false,
|
||||
"timeout": 100,
|
||||
"type": "stdio",
|
||||
"command": "npx",
|
||||
"args": ["appium-mcp@latest"],
|
||||
"env": {
|
||||
"ANDROID_HOME": "/path/to/android/sdk"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### [Skills](https://github.com/appium/skills)
|
||||
|
||||
A set of AI Agent skills to support Appium automation, for example:
|
||||
|
||||
- Help preparing Appium test environment from scratch, including common driver setup
|
||||
- Help preparing XCUITest driver and WebDriverAgent for real device automation
|
||||
|
||||
## Extension Tools
|
||||
|
||||
Appium driver or plugin developers can choose to include these tools in their driver/plugin:
|
||||
@@ -35,7 +77,7 @@ details needed for the driver/plugin have been set up correctly. The tool can be
|
||||
appium {driver|plugin} doctor <extension-name>
|
||||
```
|
||||
|
||||
It shows no results if the driver/plugin author did not implement Doctor support.
|
||||
It shows no results if the driver/plugin does not have such validation checks.
|
||||
|
||||
!!! note
|
||||
|
||||
@@ -48,6 +90,18 @@ out the documentation on [Building Doctor Checks](../developing/build-doctor-che
|
||||
|
||||
These tools are not maintained by the Appium team:
|
||||
|
||||
### [AppClaw](https://github.com/AppiumTestDistribution/AppClaw)
|
||||
|
||||
AppClaw is a CLI-based agentic AI layer for mobile automation, powered by [Appium MCP](#appium-mcp).
|
||||
Agent instructions can be passed directly via CLI, or defined as YAML flows in either structured
|
||||
or natural language syntax.
|
||||
|
||||
Supported by: `@AppiumTestDistribution`
|
||||
|
||||
```sh title="Install This Tool"
|
||||
npm install -g appclaw
|
||||
```
|
||||
|
||||
### [Appium Installer](https://github.com/AppiumTestDistribution/appium-installer)
|
||||
|
||||
Appium Installer is a command-line tool for simplifying setups of new Appium test environments.
|
||||
@@ -59,29 +113,3 @@ Supported by: `@AppiumTestDistribution`
|
||||
```sh title="Install This Tool"
|
||||
npm install -g appium-installer
|
||||
```
|
||||
|
||||
### [Jarvis Appium](https://github.com/AppiumTestDistribution/mcp-appium)
|
||||
|
||||
Jarvis Appium is a Model Context Protocol (MCP) server that provides mobile test development and
|
||||
automation capabilities using Appium.
|
||||
|
||||
Supported by: `@AppiumTestDistribution`
|
||||
|
||||
```json title="Install This Tool"
|
||||
// Add the following to your MCP client configuration
|
||||
{
|
||||
"mcpServers": {
|
||||
"jarvis-appium": {
|
||||
"disabled": false,
|
||||
"timeout": 100,
|
||||
"type": "stdio",
|
||||
"command": "npx",
|
||||
"args": ["jarvis-appium"],
|
||||
"env": {
|
||||
"ANDROID_HOME": "/path/to/android/sdk",
|
||||
"CAPABILITIES_CONFIG": "/path/to/your/capabilities.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -2,9 +2,14 @@
|
||||
title: Session Capabilities
|
||||
---
|
||||
|
||||
「Capabilities」は、Appiumセッションを開始するために使用されるパラメータセットに付けられた名前です。 セット内の情報は、セッションにどのような「Capabilities」を持たせたいかを表します。たとえば、特定のモバイルオペレーティングシステムや特定のデバイスバージョンなどです。 Capabilities はキーと値のペアとして表され、値には他のオブジェクトを含む任意の有効な JSON 型を使用できます。
|
||||
Capabilities are the core parameters used to start an Appium session. They describe various
|
||||
features that you want your session to have, for example, a certain mobile operating system or a
|
||||
certain version of a device. Capabilities are represented as key-value pairs, with values allowed
|
||||
to be any valid JSON type, including other objects. Most importantly, they cannot be changed
|
||||
during the lifecycle of the session.
|
||||
|
||||
W3C WebDriver 仕様の [Capabilities に関するセクション](https://w3c.github.io/webdriver/#capabilities) では、以下の機能を含む 10 個の標準機能のセットが定義されています:
|
||||
The capabilities used in Appium follow [the W3C WebDriver specification of the same name](https://w3c.github.io/webdriver/#capabilities).
|
||||
The WebDriver spec defines a small set of standard capabilities, including the following:
|
||||
|
||||
| Capability 名 | 型 | 説明 |
|
||||
| ---------------- | -------- | --------------------- |
|
||||
@@ -12,51 +17,64 @@ W3C WebDriver 仕様の [Capabilities に関するセクション](https://w3c.g
|
||||
| `browserVersion` | `string` | ブラウザのバージョン |
|
||||
| `platformName` | `string` | ブラウザをホストするプラットフォームの種類 |
|
||||
|
||||
While the above capabilities are commonly used by Appium drivers, they are not sufficient for
|
||||
describing Appium-specific features, such as the name of the driver to use, or the name of the app
|
||||
to launch. In order to achieve this, Appium defines its own [extension capabilities](https://w3c.github.io/webdriver/#dfn-extension-capability).
|
||||
|
||||
## 一般的なAppiumのCapabilities
|
||||
|
||||
Appium はこれらのブラウザに焦点を当てた capabilities を理解しますが、いくつかの capabilities も追加導入しています。 WebDriver 仕様によれば、非標準の「拡張 capabilities」には、capabilities を導入したベンダーを示す名前空間となる接頭辞(末尾に「:」)を含める必要があります。 Appium の接頭辞は「appium:」であるため、Appium 固有の capabilities には必ずこの接頭辞を含める必要があります。 使用しているクライアントによっては接頭辞が自動的に追加される場合もあれば、特定のインターフェースと組み合わせて追加される場合もありますが、明確にするために明示的に追加することをお勧めします。
|
||||
According to the WebDriver spec, extension capabilities must include a namespace prefix (signifying
|
||||
the vendor introducing the capability), and the namespace must end a colon (`:`). Appium's vendor
|
||||
prefix is `appium:`, and so any Appium-specific capabilities must include this prefix. Depending on
|
||||
your Appium client, the prefix may be added automatically or in conjunction with certain interfaces,
|
||||
but it is always a good practice to explicitly include it for clarity.
|
||||
|
||||
以下は様々なドライバーで認識される Appium の capabilities の一覧です:
|
||||
Here are a few commonly (but not universally!) used Appium-specific capabilities:
|
||||
|
||||
!!! info
|
||||
| Capability 名 | 型 | Description |
|
||||
| ----------------------- | -------- | --------------------------------------------------------------- |
|
||||
| `appium:automationName` | `string` | 使用するAppiumドライバの名前 |
|
||||
| `appium:udid` | `string` | The unique device identifier of a particular device to automate |
|
||||
| `appium:app` | `string` | インストール可能なアプリケーションへのパス |
|
||||
|
||||
```
|
||||
個々のドライバやプラグインは独自の capabilities をサポートしている場合があるため、具体的な capability 名のリストについては、それぞれのドキュメントを参照してください。また、一部のドライバはこれらの capabilities をすべてサポートしていない場合があります
|
||||
```
|
||||
All capabilities recognized by the Appium base driver (inherited by all drivers) can be found in the
|
||||
[Capabilities Reference document](../reference/session/caps.md). While this common capability set
|
||||
is fairly small, it can be greatly extended by Appium drivers and plugins, who can (and should)
|
||||
define their own capabilities. Make sure to reference their documentation to learn more about the
|
||||
capabilities they support. You can find a list of known drivers in the [Ecosystem Drivers](../ecosystem/drivers.md) document.
|
||||
|
||||
| <div style="width:12em">Capability 名</div> | 型 | 必須か | 説明 |
|
||||
| ------------------------------------------ | --------- | --- | ------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `platformName` | `string` | はい | アプリまたはブラウザをホストするプラットフォームの種類 |
|
||||
| `appium:automationName` | `string` | はい | 使用するAppiumドライバの名前 |
|
||||
| `browserName` | `string` | いいえ | ドライバーが特別なケースとしてWebブラウザーをサポートしている場合、起動して自動化するブラウザーの名前 |
|
||||
| `appium:app` | `string` | いいえ | インストール可能なアプリケーションへのパス |
|
||||
| `appium:deviceName` | `string` | いいえ | 自動化する特定のデバイスの名前、例:`iPhone 14`(現在のところ、iOS シミュレーターを指定する場合にのみ役立ちます。他の状況では通常、`appium:udid` 機能を使用して特定のデバイス Id を使用することをお勧めします)。 |
|
||||
| `appium:platformVersion` | `string` | いいえ | プラットフォームのバージョン(例:iOS の場合は `16.0`) |
|
||||
| `appium:newCommandTimeout` | `number` | いいえ | クライアントがこれ以上コマンドを送信してこないと判断しセッションを終了する前に、Appium サーバーがクライアントからのコマンド送信を待機する秒数。 デフォルトは `60` 秒。 ゼロに設定するとタイマーが無効になります。 |
|
||||
| `appium:noReset` | `boolean` | いいえ | true の場合、セッションの開始とクリーンアップ中に通常のリセット処理を回避するように Appium ドライバーに指示します (デフォルトは `false`) |
|
||||
| `appium:fullReset` | `boolean` | いいえ | true の場合、Appium ドライバーに通常のリセット処理に追加の手順を追加して、環境の再現性を最大限に高めるように指示します (デフォルトは `false`) |
|
||||
| `appium:eventTimings` | `boolean` | いいえ | true の場合、Appium ドライバーに [Event Timings](./event-timing.md) を収集するように指示します (デフォルトは `false`) |
|
||||
| `appium:printPageSourceOnFindFailure` | `boolean` | いいえ | true の場合、要素の検索リクエストが失敗するたびにページソースを収集し、Appium ログに出力します (デフォルトは `false`) |
|
||||
Drivers are also able to place more complex constraints on capabilities as a group. For example,
|
||||
the XCUITest driver recommends that at least one of `browserName`, `appium:app`, or `appium:bundleId`
|
||||
is included in the capabilities, otherwise it will not be able to auto-install or auto-launch any
|
||||
application. Each driver will document how it interprets these capabilities and any other
|
||||
platform-specific requirements.
|
||||
|
||||
ドライバーの中には、capabilitiesのより複雑な制約をグループとして設定しているものもあります。 たとえば、`appium:app` および `browserName` capabilities は上記では必須ではないと記載していますが、特定のアプリでセッションを開始する場合、XCUITest ドライバーは、`appium:app`、`browserName`、または `appium:bundleId` の少なくとも1 つが capabilities に含まれていることが必要です (含まれていない場合、どのアプリをインストールまたは起動すればよいか判断できないため、ホーム画面からセッションが開かれます)。 各ドライバーは、これらの capabilities やその他のプラットフォーム固有の要件をどのように解釈するかを記述しています。
|
||||
The way to construct capabilities and start a session will likely differ depending on your Appium
|
||||
client. For examples of doing this in each client library, head to the [Ecosystem Clients](../ecosystem/clients.md)
|
||||
page and click through to the appropriate client documentation.
|
||||
|
||||
!!! note
|
||||
|
||||
```
|
||||
Capabilitiesは、セッション開始時に使用されるパラメータのようなものです。Capabilitiesが送信され、セッションが開始された後変更できません。ドライバーがセッション中に動作の一部を更新する場合、capabilitiesの代わりに、またはcapabilitiesに加えて、[Settings](./settings.md)も利用可能です。
|
||||
Once your capabilities are sent to the server and the session is started, they cannot be
|
||||
changed. If a driver supports updating its behaviour during a session, it will use the
|
||||
[Settings API](./settings.md) for this purpose.
|
||||
```
|
||||
|
||||
各 Appium クライアントには、capabilities を構築し、セッションを開始する独自の方法があります。 各クライアントライブラリでこれを行う例については、[エコシステム](../ecosystem/index.md) ページにアクセスし、適切なクライアントドキュメントをクリックしてください。
|
||||
|
||||
## BiDi プロトコルのサポート
|
||||
|
||||
Appiumは、base-driver 9.5.0以降で[WebDriver BiDi](https://w3c.github.io/webdriver-bidi/)プロトコルをサポートしています。
|
||||
実際の動作は個々のドライバーによって異なりますが、Appium と base-driver はプロトコルをサポートしています。
|
||||
ドライバーが BiDi プロトコルをサポートしているかどうか、また、どのようなコマンド/イベントをサポートしているかはドキュメントで確認してください。
|
||||
In addition to the standard WebDriver protocol (now known as WebDriver Classic), Appium supports the
|
||||
[WebDriver BiDi](https://w3c.github.io/webdriver-bidi/) protocol. Support for this protocol is
|
||||
opt-in, and requires the use of the standard `webSocketUrl` capability.
|
||||
|
||||
| Capability 名 | 型 | 説明 |
|
||||
| -------------- | --------- | ------------------------- |
|
||||
| `webSocketUrl` | `boolean` | セッションで BiDi プロトコルを有効にします。 |
|
||||
| Capability Name | 型 | 説明 |
|
||||
| --------------- | --------- | ----------------------------------------------- |
|
||||
| `webSocketUrl` | `boolean` | Whether BiDi protocol is enabled in the session |
|
||||
|
||||
All BiDi commands supported by the Appium base driver (inherited by all drivers) can be found in the
|
||||
[BiDi Protocol API Reference document](../reference/api/bidi.md). Similarly to WebDriver Classic
|
||||
commands, individual Appium drivers and plugins can define their own supported standard and custom
|
||||
BiDi commands, so make sure to reference their documentation.
|
||||
|
||||
## `appium:options` を使用して機能をグループ化する
|
||||
|
||||
@@ -99,8 +117,7 @@ creates in response to a new session request. This is through the concept of "al
|
||||
!!! note
|
||||
|
||||
```
|
||||
Check out the [spec itself](https://w3c.github.io/webdriver/#processing-capabilities) or
|
||||
a [summarized version](https://github.com/jlipps/simple-wd-spec#processing-capabilities) for
|
||||
Check out the [spec itself](https://w3c.github.io/webdriver/#processing-capabilities) for
|
||||
a more in-depth description of how capabilities are processed.
|
||||
```
|
||||
|
||||
|
||||
@@ -3,27 +3,27 @@ title: Appium Server Security
|
||||
---
|
||||
|
||||
The Appium team makes every effort to ensure the security of the Appium server. This is especially
|
||||
important when Appium is run in a multitenant environment, or when multiple users are running
|
||||
sessions on the same Appium server. In general, you can only safely enable all of Appium's features if
|
||||
all the following are true:
|
||||
important when Appium is run in a multi-tenant environment, or when multiple users are running
|
||||
sessions on the same Appium server. To ensure a safe environment for Appium's purposes, all of the
|
||||
following should be true:
|
||||
|
||||
- You're running your own Appium server locally or within a protected internal network
|
||||
- You're not sharing it with any untrusted parties
|
||||
- You don't expose Appium's port(s) to the wider internet
|
||||
|
||||
But because many Appium users might not be able to guarantee such a safe environment, the Appium
|
||||
team puts many features behind a security protection mechanism, which forces system admins (the
|
||||
people who are in charge of starting the Appium server) to _explicitly opt-in_ to these features.
|
||||
(Third-party driver and plugin authors can also hide behaviour behind security
|
||||
flags.)
|
||||
But because not all Appium hosts can guarantee such a safe environment, certain insecure Appium
|
||||
features are disabled by default, and require explicit opt-in in order to enable them. Most
|
||||
importantly, this can _only_ be done by the Appium server _host_, and Appium _client_ sessions are
|
||||
not allowed to change this.
|
||||
|
||||
For security reasons, Appium client sessions can _not_ request feature enablement via capabilities.
|
||||
This is the responsibility of the server admin who configures and launches the Appium server.
|
||||
While it is possible for an Appium host to simply enable all insecure features at once, each
|
||||
feature also has a unique name, which can be used for granular control over the server state.
|
||||
|
||||
## Security Server Args
|
||||
|
||||
The [Server CLI](../reference/cli/server.md) doc outlines three relevant arguments which may be passed to
|
||||
Appium, when starting it from the command line:
|
||||
Enabling or disabling insecure features is done via [Appium server launch arguments](../reference/cli/server.md)
|
||||
or [configuration file](./config.md). The former document outlines three relevant arguments for
|
||||
achieving this:
|
||||
|
||||
| <div style="width:10em">Parameter</div> | Description |
|
||||
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
@@ -31,36 +31,30 @@ Appium, when starting it from the command line:
|
||||
| `--allow-insecure` | Turns on _only_ specified features, except those blocked by `--deny-insecure`. Has no effect when used in combination with `--relaxed-security` |
|
||||
| `--deny-insecure` | Explicitly turns _off_ specified features, overriding `--relaxed-security` and `--allow-insecure` |
|
||||
|
||||
All of the above arguments can also be specified in the [Appium Configuration file](./config.md).
|
||||
|
||||
Features passed to `--allow-insecure`/`--deny-insecure` must be specified as a comma-separated list,
|
||||
and each feature in the list must additionally include a prefix, indicating the driver to which the
|
||||
feature should apply. The prefix can be either the driver's `automationName`, or the wildcard (`*`)
|
||||
symbol, if the feature should be applied to all drivers. The prefix and feature name are separated
|
||||
using the colon character (`:`).
|
||||
and each feature in the list must additionally include a prefix, indicating the driver to whose
|
||||
sessions the feature should apply. The prefix can be either the driver's `automationName`, or the
|
||||
wildcard (`*`) symbol, if the feature should be applied to all drivers. The prefix and feature name
|
||||
are separated using the colon character (`:`).
|
||||
|
||||
For example, `first:foo` refers to the `foo` feature for the `first` driver, whereas `*:bar` refers
|
||||
to the `bar` feature for all drivers.
|
||||
|
||||
## Insecure Features
|
||||
|
||||
Each Appium driver is responsible for its own security, and can create its own feature names. Thus,
|
||||
you should read through the documentation for a particular driver to know which feature names it
|
||||
might use. Here is an incomplete list of examples from some of Appium's official drivers:
|
||||
Almost all insecure features are defined on a per-driver or plugin basis, so make sure to read the
|
||||
documentation for a particular driver/plugin to know which feature names it might use.
|
||||
|
||||
| <div style="width:12em">Feature Name</div> | Description | Supported Extension(s) |
|
||||
| ------------------------------------------ | --------------------------------------------------------------------------------------- | ---------------------------------------------- |
|
||||
| `get_server_logs` | Allows retrieving of Appium server logs via the Webdriver log interface | IOS, XCUITest, Android, UiAutomator2, Espresso |
|
||||
| `adb_shell` | Allows execution of arbitrary shell commands via ADB, using the `mobile: shell` command | Android, UiAutomator2, Espresso |
|
||||
| `record_audio` | Allow recording of host machine audio inputs | XCUITest |
|
||||
| `execute_driver_script` | Allows sending a request that has multiple Appium commands. | Execute Driver Plugin |
|
||||
Certain insecure features are also defined on the Appium server itself. For a list of these
|
||||
features, as well as the features defined in official plugins, see
|
||||
[the Insecure Features CLI Reference](../reference/cli/insecure-features.md) doc.
|
||||
|
||||
Some insecure features operate on the server level and do not require a driver session. Enabling
|
||||
these features require using the wildcard prefix:
|
||||
!!! note
|
||||
|
||||
| <div style="width:12em">Feature Name</div> | Description |
|
||||
| ------------------------------------------ | ------------------------------------------------------------------------------- |
|
||||
| `session_discovery` | Allows retrieving the list of active server sessions via `GET /appium/sessions` |
|
||||
```
|
||||
If you are a driver or plugin author and want to implement insecure features of your own, check
|
||||
out the [Building Drivers documentation](../developing/build-drivers.md#understand-server-assigned-driver-properties-and-security-flags).
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -30,9 +30,9 @@ Appiumのドキュメントにようこそ! Appiumはオープンソースプ
|
||||
</a>
|
||||
</div>
|
||||
<div class="homepageSponsor">
|
||||
<a href="https://lambdatest.com/?utm_source=appium.io&utm_medium=organic&utm_campaign=june_25&utm_term=sk&utm_content=webpage">
|
||||
<img src="assets/images/sponsor-logo-lambdatest-dark.png#only-dark" style="width: 220px;" />
|
||||
<img src="assets/images/sponsor-logo-lambdatest-light.png#only-light" style="width: 220px;" />
|
||||
<a href="https://www.testmuai.com">
|
||||
<img src="assets/images/sponsor-logo-testmuai-dark.png#only-dark" style="width: 220px;" />
|
||||
<img src="assets/images/sponsor-logo-testmuai-light.png#only-light" style="width: 220px;" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -397,6 +397,45 @@ Deletes the virtual sensor with the type identified by `:sensorType`.
|
||||
|
||||
`null`
|
||||
|
||||
## Global Privacy Control Protocol
|
||||
|
||||
The [Global Privacy Control protocol](https://www.w3.org/TR/gpc) (GPC) is an extension of the W3C
|
||||
WebDriver protocol.
|
||||
|
||||
### setGlobalPrivacyControl
|
||||
|
||||
```
|
||||
POST /session/:sessionId/privacy
|
||||
```
|
||||
|
||||
> GPC documentation: [Set Global Privacy Control](https://www.w3.org/TR/gpc/#set-global-privacy-control)
|
||||
|
||||
Sets the value of the do-not-sell-or-share preference for the current session.
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Description | Type |
|
||||
| ----- | -------------------------------------------------------------------- | ------- |
|
||||
| `gpc` | Whether the browser should perform do-not-sell-or-share interactions | boolean |
|
||||
|
||||
#### Response
|
||||
|
||||
`null`
|
||||
|
||||
### getGlobalPrivacyControl
|
||||
|
||||
```
|
||||
GET /session/:sessionId/privacy
|
||||
```
|
||||
|
||||
> GPC documentation: [Get Global Privacy Control](https://www.w3.org/TR/gpc/#get-global-privacy-control)
|
||||
|
||||
Retrieves the value of the do-not-sell-or-share preference for the current session.
|
||||
|
||||
#### Response
|
||||
|
||||
`boolean` - the preference value
|
||||
|
||||
## Permissions Protocol
|
||||
|
||||
The [Permissions protocol](https://www.w3.org/TR/permissions/) is an extension of the W3C WebDriver
|
||||
@@ -524,6 +563,32 @@ Retrieves the available log types that can be used to call the [`getLog`](#getlo
|
||||
|
||||
`string[]` - an array of log types
|
||||
|
||||
## Storage Access Protocol
|
||||
|
||||
The [Storage Access protocol](https://privacycg.github.io/storage-access/) is an extension of the
|
||||
W3C WebDriver protocol.
|
||||
|
||||
### setStorageAccess
|
||||
|
||||
```
|
||||
POST /session/:sessionId/storageaccess
|
||||
```
|
||||
|
||||
> Storage Access documentation: [Set Storage Access](https://privacycg.github.io/storage-access/#set-storage-access-command)
|
||||
|
||||
Sets the storage access policy of the current browsing context.
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Description | Type |
|
||||
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
|
||||
| `blocked` | Whether storage access should be blocked (`true`) or allowed (`false`) | boolean |
|
||||
| `origin` | The origin to which the policy should be applied. Must be either a valid URL, or an asterisk (`*`) if the policy should apply to all origins. | string |
|
||||
|
||||
#### Response
|
||||
|
||||
`null`
|
||||
|
||||
## Web Authentication Protocol
|
||||
|
||||
The [Web Authentication protocol](https://w3c.github.io/webauthn/) (WebAuthn) is an extension of
|
||||
|
||||
@@ -224,7 +224,7 @@ Deletes a file in the storage.
|
||||
#### Response
|
||||
|
||||
`boolean` - `true` upon successful file deletion, or `false` if the file does not exist in
|
||||
the storage
|
||||
the storage, or if the delete request is invalid.
|
||||
|
||||
### listStorageItems
|
||||
|
||||
|
||||
@@ -118,6 +118,12 @@ appium {driver|plugin} install <install-spec>
|
||||
appium driver install git://github.com/appium/appium-xcuitest-driver.git --source=git --package=appium-xcuitest-driver
|
||||
```
|
||||
|
||||
- Install a branch of XCUITest driver repository using a Git URL:
|
||||
|
||||
```
|
||||
appium driver install git://github.com/appium/appium-xcuitest-driver.git#specific-branch --source=git --package=appium-xcuitest-driver
|
||||
```
|
||||
|
||||
## `list`
|
||||
|
||||
Lists all installed extensions, plus all official extensions that are not installed.
|
||||
@@ -135,6 +141,7 @@ appium {driver|plugin} list
|
||||
| `--installed` | Only list all installed extensions | boolean |
|
||||
| `--json` | Return the result in JSON format | boolean |
|
||||
| `--updates` | List all extensions along with information on whether newer versions are available. Only supported for extensions installed via `npm`. | boolean |
|
||||
| `--verbose` | Show additional details for each extension | boolean |
|
||||
|
||||
#### Example
|
||||
|
||||
|
||||
@@ -31,5 +31,6 @@ The executable has four main subcommands: `server`, `driver`, `plugin`, and `set
|
||||
|
||||
</div>
|
||||
|
||||
Appium also recognizes several [environment variables](./env-vars.md), which may be used for
|
||||
advanced configuration.
|
||||
The Appium server also recognizes several [environment variables](./env-vars.md) and
|
||||
[insecure feature names](./insecure-features.md), though drivers and plugins can also define
|
||||
variables and features of their own.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Insecure Features
|
||||
---
|
||||
|
||||
The Appium server implements [a security protection mechanism](../../guides/security.md) that
|
||||
allows the management of various insecure features.
|
||||
|
||||
The following features are defined on the server level and can be used even without drivers, but
|
||||
they can only be enabled using the wildcard (`*`) prefix:
|
||||
|
||||
| Feature Name | Description |
|
||||
| ------------------- | ------------------------------------------------------------------------------- |
|
||||
| `session_discovery` | Allows retrieving the list of active server sessions via `GET /appium/sessions` |
|
||||
|
||||
Of course, Appium drivers and plugins are free to define additional insecure features of their own.
|
||||
The following features are defined by official plugins:
|
||||
|
||||
| Feature Name | Plugin | Description |
|
||||
| ----------------------- | ---------------- | ---------------------------------------------------------- |
|
||||
| `execute_driver_script` | `execute_driver` | Allows sending a request that has multiple Appium commands |
|
||||
@@ -48,6 +48,8 @@ appium
|
||||
| `--log-no-colors` | Disable colors in the server log | boolean | `false` |
|
||||
| `--log-timestamp` | Show timestamps in the server log | boolean | `false` |
|
||||
| `--long-stacktrace` | Add long stack traces to log entries. Recommended for debugging only. | boolean | `false` |
|
||||
| `--max-ipc-data-size` | Maximum byte size of IPC message objects. | integer | `1048576` (1MB) |
|
||||
| `--max-ipc-topics` | Maximum number of IPC topics per session. | integer | `1000` |
|
||||
| `--no-perms-check` | Skip various permission checks on the server startup | boolean | `false` |
|
||||
| `--nodeconfig` | JSON configuration for registering Appium as a node with Selenium Grid 3 | object | |
|
||||
| `--plugin` | Plugin-specific configuration. Keys should correspond to plugin package names | object | |
|
||||
|
||||
@@ -5,8 +5,8 @@ hide:
|
||||
title: Reference
|
||||
---
|
||||
|
||||
This section of the Appium documentation provides a reference to the two main interfaces within the
|
||||
Appium server: the command-line executable, and the supported API endpoints.
|
||||
This section of the Appium documentation provides a reference to the core interfaces supported within the
|
||||
Appium server:
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
@@ -16,10 +16,16 @@ Appium server: the command-line executable, and the supported API endpoints.
|
||||
|
||||
Learn how to use the Appium command-line executable
|
||||
|
||||
- :material-lan-connect: [**Session Properties**](./session/index.md)
|
||||
|
||||
---
|
||||
|
||||
See the values of global Appium session properties
|
||||
|
||||
- :material-cloud-braces: [**API Endpoints**](./api/index.md)
|
||||
|
||||
---
|
||||
|
||||
View endpoints supported by the Appium server
|
||||
View endpoints supported by the core Appium server
|
||||
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Capabilities
|
||||
---
|
||||
|
||||
The following [capabilities](../../guides/caps.md) are recognized by the Appium server/base driver,
|
||||
and are therefore supported by all drivers as well. Some capabilities are directly handled by the
|
||||
server/base driver, while others are only validated before being passed to the actual driver.
|
||||
|
||||
!!! note
|
||||
|
||||
Capabilities not listed here will _not_ be rejected by Appium: they will simply be forwarded
|
||||
directly to the active driver/plugin.
|
||||
|
||||
### Required Capabilities
|
||||
|
||||
These capabilities are used in the Appium server/base driver, and are explicitly required in all
|
||||
Appium sessions.
|
||||
|
||||
| Capability | Description | Type |
|
||||
| ----------------------- | ------------------------------------------- | -------- |
|
||||
| `platformName` | Type of platform hosting the app or browser | `string` |
|
||||
| `appium:automationName` | Name of the Appium driver to use | `string` |
|
||||
|
||||
### Optional Capabilities
|
||||
|
||||
These capabilities are used in the Appium server/base driver, but are optional, and may have a
|
||||
default value.
|
||||
|
||||
| <div style="width:19em">Capability</div> | Description | Type | Default |
|
||||
| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
|
||||
| `webSocketUrl` | Toggle support of the WebDriver BiDi protocol | `boolean` | |
|
||||
| `appium:eventTimings` (deprecated) | Toggle collection of [Event Timings](../../guides/event-timing.md). This capability is deprecated - please use the [`getLogEvents`](../api/appium.md#getlogevents) endpoint instead. | `boolean` | |
|
||||
| `appium:newCommandTimeout` | Number of seconds the Appium server should wait for clients to send commands before stopping the session. A value of `0` disables the timeout. | `number` | `60` |
|
||||
| `appium:printPageSourceOnFindFailure` | Toggle retrieval of the the page source and its printing to the Appium log, whenever a request to find an element fails | `boolean` | |
|
||||
|
||||
### Validated Capabilities
|
||||
|
||||
These capabilities are not directly used in the Appium server/base driver, but are still subject to
|
||||
validation checks due to their relevance in other drivers. The actual handling of these
|
||||
capabilities is optional and entirely driver-dependent.
|
||||
|
||||
| Capability | Validation |
|
||||
| --------------------------------------------------- | ------------------------------------------------------------- |
|
||||
| `platformVersion` | Must be `string` |
|
||||
| `appium:app` | Must be `string`; empty values are ignored |
|
||||
| `appium:autoLaunch` (deprecated) | Must be `boolean` |
|
||||
| `appium:autoWebview` | Must be `boolean` |
|
||||
| `appium:fullReset` | Must be `boolean`; mutually exclusive with `appium:noReset` |
|
||||
| `appium:language` | Must be `string` |
|
||||
| `appium:locale` | Must be `string` |
|
||||
| `appium:orientation` | Must be either `LANDSCAPE` or `PORTRAIT` |
|
||||
| `appium:noReset` | Must be `boolean`; mutually exclusive with `appium:fullReset` |
|
||||
| `appium:udid` | Must be `string` |
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Session Properties
|
||||
---
|
||||
|
||||
An Appium session has several key properties, each with its own set of supported values:
|
||||
capabilities, execute methods, settings, locator strategies, and others. The supported values for
|
||||
each property are primarily defined by the active driver and plugins, but some properties also have
|
||||
common values provided by the Appium server and its base driver:
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- [**Capabilities**](./caps.md)
|
||||
|
||||
A small set of basic capabilities
|
||||
|
||||
- [**Command Endpoints**](../api/index.md)
|
||||
|
||||
The core set of API endpoints
|
||||
|
||||
</div>
|
||||
@@ -26,3 +26,4 @@ Here you can find links to additional Appium resources around the web:
|
||||
- [AppiumConf 2021](https://www.youtube.com/playlist?list=PL9Z-JgiTsOYRCcJhDfmKAah9XmAp2b903)
|
||||
- [AppiumConf 2024](https://www.youtube.com/playlist?list=PL9Z-JgiTsOYQaU5i5LJtAWlh5WVZPi3If)
|
||||
- [SeleniumConf & AppiumConf 2025](https://www.youtube.com/playlist?list=PLRdSclUtJDYV2R92TLbmwxws6clruuTjH)
|
||||
- [SeleniumConf & AppiumConf 2026](https://www.youtube.com/playlist?list=PLRdSclUtJDYVgVqdKnSyBLBmFdA0KE_Dk)
|
||||
|
||||
@@ -22,6 +22,11 @@ Hub.
|
||||
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.testmuai.com">
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-testmuai-dark.png#only-dark" width="250" alt="TestMu AI (formerly LambdaTest)" />
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-testmuai-light.png#only-light" width="250" alt="TestMu AI (formerly LambdaTest)" />
|
||||
</a>
|
||||
|
||||
## Strategic Partners
|
||||
|
||||
We are very grateful for the financial and marketing support of our exclusive Strategic Partners,
|
||||
@@ -33,9 +38,9 @@ contributors!
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-browserstack-light.png#only-light" width="250" alt="BrowserStack" />
|
||||
</a>
|
||||
|
||||
<a href="https://lambdatest.com/?utm_source=appium.io&utm_medium=organic&utm_campaign=june_25&utm_term=sk&utm_content=webpage">
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-lambdatest-dark.png#only-dark" width="250" alt="LambdaTest" />
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-lambdatest-light.png#only-light" width="250" alt="LambdaTest" />
|
||||
<a href="https://www.testmuai.com">
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-testmuai-dark.png#only-dark" width="250" alt="TestMu AI (formerly LambdaTest)" />
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-testmuai-light.png#only-light" width="250" alt="TestMu AI (formerly LambdaTest)" />
|
||||
</a>
|
||||
|
||||
## Gold Sponsors
|
||||
|
||||
@@ -42,6 +42,10 @@ nav:
|
||||
- reference/cli/extensions.md
|
||||
- reference/cli/setup.md
|
||||
- reference/cli/env-vars.md
|
||||
- reference/cli/insecure-features.md
|
||||
- Session Properties:
|
||||
- reference/session/index.md
|
||||
- reference/session/caps.md
|
||||
- API Endpoints:
|
||||
- reference/api/index.md
|
||||
- reference/api/webdriver.md
|
||||
|
||||
@@ -42,6 +42,10 @@ nav:
|
||||
- reference/cli/extensions.md
|
||||
- reference/cli/setup.md
|
||||
- reference/cli/env-vars.md
|
||||
- reference/cli/insecure-features.md
|
||||
- Session Properties:
|
||||
- reference/session/index.md
|
||||
- reference/session/caps.md
|
||||
- API Endpoints:
|
||||
- reference/api/index.md
|
||||
- reference/api/webdriver.md
|
||||
|
||||
@@ -9,40 +9,44 @@ theme:
|
||||
nav:
|
||||
- 欢迎使用: index.md
|
||||
- 博客: blog/index.md
|
||||
- 简介:
|
||||
- 简介:
|
||||
- intro/index.md
|
||||
- 背景:
|
||||
- 背景:
|
||||
- intro/appium.md
|
||||
- intro/drivers.md
|
||||
- intro/clients.md
|
||||
- intro/history.md
|
||||
- 快速开始:
|
||||
- 快速开始:
|
||||
- quickstart/index.md
|
||||
- quickstart/requirements.md
|
||||
- quickstart/install.md
|
||||
- quickstart/uiauto2-driver.md
|
||||
- 写一个测试:
|
||||
- 写一个测试:
|
||||
- quickstart/test-js.md
|
||||
- quickstart/test-py.md
|
||||
- quickstart/test-java.md
|
||||
- quickstart/test-rb.md
|
||||
- quickstart/test-dotnet.md
|
||||
- quickstart/next-steps.md
|
||||
- 生态系统:
|
||||
- 生态系统:
|
||||
- ecosystem/index.md
|
||||
- ecosystem/drivers.md
|
||||
- ecosystem/clients.md
|
||||
- ecosystem/plugins.md
|
||||
- ecosystem/tools.md
|
||||
- 参考:
|
||||
- 参考:
|
||||
- reference/index.md
|
||||
- 命令行界面:
|
||||
- 命令行界面:
|
||||
- reference/cli/index.md
|
||||
- reference/cli/server.md
|
||||
- reference/cli/extensions.md
|
||||
- reference/cli/setup.md
|
||||
- reference/cli/env-vars.md
|
||||
- API 端点:
|
||||
- reference/cli/insecure-features.md
|
||||
- Session Properties:
|
||||
- reference/session/index.md
|
||||
- reference/session/caps.md
|
||||
- API 端点:
|
||||
- reference/api/index.md
|
||||
- reference/api/webdriver.md
|
||||
- reference/api/bidi.md
|
||||
@@ -51,11 +55,11 @@ nav:
|
||||
- reference/api/appium.md
|
||||
- reference/api/others.md
|
||||
- reference/api/plugins.md
|
||||
- 指南:
|
||||
- 迁移:
|
||||
- 指南:
|
||||
- 迁移:
|
||||
- guides/migrating-2-to-3.md
|
||||
- guides/migrating-1-to-2.md
|
||||
- 服务器/驱动程序配置:
|
||||
- 服务器/驱动程序配置:
|
||||
- guides/managing-exts.md
|
||||
- guides/branch-testing.md
|
||||
- guides/config.md
|
||||
@@ -65,24 +69,24 @@ nav:
|
||||
- guides/grid.md
|
||||
- guides/caching.md
|
||||
- guides/tls.md
|
||||
- 会话配置:
|
||||
- 会话配置:
|
||||
- guides/caps.md
|
||||
- guides/settings.md
|
||||
- guides/execute-methods.md
|
||||
- guides/context.md
|
||||
- guides/event-timing.md
|
||||
- 更多资源:
|
||||
- 更多资源:
|
||||
- resources/index.md
|
||||
- 开发:
|
||||
- 开发:
|
||||
- developing/index.md
|
||||
- developing/build-drivers.md
|
||||
- developing/build-plugins.md
|
||||
- developing/build-docs.md
|
||||
- developing/build-doctor-checks.md
|
||||
- developing/sensitive.md
|
||||
- 开发者参考:
|
||||
- 开发者参考:
|
||||
- developing/config-system.md
|
||||
- 贡献:
|
||||
- 贡献:
|
||||
- contributing/index.md
|
||||
- 赞助者:
|
||||
- 赞助者:
|
||||
- sponsors/index.md
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@@ -5,7 +5,7 @@
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-browserstack-dark.png" />
|
||||
</a>
|
||||
|
||||
<a href="https://lambdatest.com/?utm_source=appium.io&utm_medium=organic&utm_campaign=june_25&utm_term=sk&utm_content=webpage">
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-lambdatest-dark.png" />
|
||||
<a href="https://www.testmuai.com">
|
||||
<img src="/docs/en/latest/assets/images/sponsor-logo-testmuai-dark.png" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -20,7 +20,7 @@ const {
|
||||
DOCS_REMOTE,
|
||||
LATEST_ALIAS,
|
||||
} = require('./utils');
|
||||
const path = require('path');
|
||||
const path = require('node:path');
|
||||
const semver = require('semver');
|
||||
const {version} = require('../../package.json');
|
||||
|
||||
@@ -31,6 +31,9 @@ const preview = Boolean(process.env.APPIUM_DOCS_PREVIEW);
|
||||
|
||||
const push = Boolean(process.env.APPIUM_DOCS_PUBLISH);
|
||||
|
||||
/**
|
||||
* Builds and optionally deploys docs for each supported language.
|
||||
*/
|
||||
async function main() {
|
||||
log.info(`Building Appium docs and committing to ${DOCS_BRANCH}`);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/* eslint-disable promise/prefer-await-to-callbacks */
|
||||
/* eslint-disable promise/prefer-await-to-then */
|
||||
|
||||
const path = require('path');
|
||||
const path = require('node:path');
|
||||
const {fs} = require('@appium/support');
|
||||
const {AppiumConfigJsonSchema} = require('@appium/schema');
|
||||
|
||||
@@ -12,6 +12,9 @@ const DOC_PATH = path.resolve(__dirname, '..', 'en', 'cli', 'args.md');
|
||||
const START_TAG = `<!-- AUTOGEN-START -->`;
|
||||
const STOP_TAG = `<!-- AUTOGEN-STOP -->`;
|
||||
|
||||
/**
|
||||
* Regenerates the CLI arguments table in docs.
|
||||
*/
|
||||
async function main() {
|
||||
console.log(`Gathering current cli doc file contents...`);
|
||||
const [preStart, postEnd] = await getDocParts();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// for simplicity this file is not transpiled and is run directly via an npm script
|
||||
//
|
||||
const {logger} = require('@appium/support');
|
||||
const path = require('path');
|
||||
const path = require('node:path');
|
||||
|
||||
const log = logger.getLogger('Docs');
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ title: 对Appium 的贡献
|
||||
|
||||
Appium项目离不开来自公司和志愿者的代码、文档、维护和支持的众多贡献。 因此,我们欢迎贡献!
|
||||
|
||||
有许多不同的方式可以帮助项目——请参阅下方了解您可以做的一切以及每个贡献方法的流程。 请注意,无论您如何贡献,您的参与都受我们的[行为准则](https://github.com/appium/appium/blob/master/CONDUCT.md)管辖。
|
||||
有许多不同的方式可以帮助项目——请参阅下方了解您可以做的一切以及每个贡献方法的流程。 请注意,无论您如何贡献,您的参与都受我们的[行为准则](https://github.com/appium/.github/blob/master/CODE_OF_CONDUCT.md)管辖。
|
||||
|
||||
## 加入讨论论坛
|
||||
|
||||
|
||||
@@ -570,6 +570,33 @@ capability), and then to set an internal field to that value, so that it can be
|
||||
bidiProxyUrl`. Once all this is in place, Appium will proxy BiDi commands from the client straight
|
||||
to the upstream connection.
|
||||
|
||||
### Understand server-assigned driver properties and security flags
|
||||
|
||||
When your driver is running under the main Appium server, Appium assigns a small set of
|
||||
server-related properties on your driver instance when a session is created:
|
||||
|
||||
- `cliArgs`: Driver-specific configuration derived from the Appium server’s CLI flags and/or
|
||||
configuration files (for example via the `server.driver.<your-driver-name>` section). These
|
||||
options are **not** user capabilities and cannot be influenced directly by test code.
|
||||
- `server`, `serverHost`, `serverPort`, `serverPath`: Information about the HTTP server that is
|
||||
hosting your driver. These values reflect how the Appium server was started (for example the
|
||||
`--address`, `--port`, and `--base-path` flags) and are useful when your driver needs to construct
|
||||
URLs that point back to the Appium server itself (for example when setting up proxies, webhooks,
|
||||
or other callbacks).
|
||||
|
||||
`BaseDriver` and `AppiumDriver` also cooperate to expose security-related flags on your driver
|
||||
instance:
|
||||
|
||||
- `relaxedSecurityEnabled`: Indicates whether the server is running with relaxed security enabled
|
||||
(for example via `--relaxed-security`).
|
||||
- `allowInsecure`: A list of insecure features which are explicitly allowed for this driver (derived
|
||||
from server-level options like `--allow-insecure`).
|
||||
- `denyInsecure`: A list of insecure features which are explicitly disabled for this driver (derived
|
||||
from server-level options like `--deny-insecure`).
|
||||
|
||||
See [Hide behaviour behind security flags](#hide-behaviour-behind-security-flags) for how to use
|
||||
these flags in your driver (e.g. via `isFeatureEnabled` and `assertFeatureEnabled`).
|
||||
|
||||
### Extend the existing protocol with new commands
|
||||
|
||||
You may find that the existing commands don't cut it for your driver. If you want to expose
|
||||
@@ -864,3 +891,120 @@ this.onUnexpectedShutdown(handler)
|
||||
|
||||
`handler` should be a function which receives an error object (representing the reason for the
|
||||
unexpected shutdown).
|
||||
|
||||
### Send messages to plugins running on the same session
|
||||
|
||||
Appium's driver and plugin architecture means that a single driver and any number of plugins can be
|
||||
running together for a current session. The driver and plugins don't really know anything about
|
||||
each other though, which can make coordination potentially difficult. Without creating any kind of
|
||||
tight coupling between drivers or plugins, it's possible for drivers and plugins to communicate
|
||||
along a pub/sub style message bus. With Appium's IPC feature, "message" means a combination of
|
||||
"data" (the data intended to be published or received), and metadata (timestamp, the name of the
|
||||
publisher, etc...).
|
||||
|
||||
Drivers and plugins can implement an instance method called `async onIpcInit`, in which they will
|
||||
know that the IPC channel for the session is now active. At this point, they have access to the
|
||||
following methods:
|
||||
|
||||
#### `ipcSubscribe<T>(topic: string): IIpcSubscription`
|
||||
|
||||
This method allows a driver or plugin to subscribe to a topic on the IPC channel for the session.
|
||||
Topics are simply strings. To coordinate effectively, drivers or plugins would use the same topic
|
||||
string (so this would be something advertised in the driver/plugin documentation).
|
||||
|
||||
The result of this call is an `IpcSubscription` object that allows:
|
||||
|
||||
- Looping through messages on the topic via an async generator
|
||||
- Hooking up an event handler for new messages
|
||||
- Getting the last message sent on the topic
|
||||
- Publishing a message to the topic
|
||||
- Unsubscribing from the topic
|
||||
|
||||
#### `IpcSubscription` object
|
||||
|
||||
Here is an example of how subscribing and use of these subscription methods might work:
|
||||
|
||||
```ts
|
||||
async onIpcInit() {
|
||||
// we know at this point in our driver/plugin lifecycle that we can use IPC methods
|
||||
type MyMessageData = {myData: string}; // let's say the message data for this channel has this shape
|
||||
|
||||
const subscription = this.ipcSubscribe<MyMessageData>('coolTopic');
|
||||
|
||||
// listen for new messages on topic
|
||||
subscription.on('message', (message) => {
|
||||
console.log(message.data); // {myData: 'something'}
|
||||
});
|
||||
|
||||
// publish data to the topic; might throw if the data is larger than configured max size, or we
|
||||
// are no longer subscribed
|
||||
await subscription.publish({myData: 'hi'});
|
||||
|
||||
// get last message sent to topic
|
||||
const {data} = subscription.getMessage() ?? {data: null};
|
||||
// data = {myData: 'hi'}
|
||||
|
||||
// unsubscribe
|
||||
subscription.unsubscribe(); // returns true if we unsubscribed and false if no subscription existed
|
||||
}
|
||||
```
|
||||
|
||||
With a subscription object, we can also iterate async over it to receive new messages:
|
||||
|
||||
```ts
|
||||
for await (const message of subscription) {
|
||||
// here we have a message and can unwrap its data
|
||||
}
|
||||
```
|
||||
|
||||
Note that the iteration will stop when the subscription ends (i.e., when `unsubscribe` is called).
|
||||
|
||||
You can also check whether the subscription is still active (if your subscribe and unsubscribe
|
||||
logic is not locally connected):
|
||||
|
||||
```ts
|
||||
if (subscription.isActive) {
|
||||
// we know we have not yet unsubscribed
|
||||
}
|
||||
```
|
||||
|
||||
If the subscription is not active, attempts to call `subscription.publish` will throw an error.
|
||||
|
||||
#### `IpcMessage` object
|
||||
|
||||
When you get a message on a topic, it has the following shape:
|
||||
|
||||
```ts
|
||||
export type IpcMessage<T> = {
|
||||
publisher: string, // the id of the publishing object (typically of the form <ClassName>@<uniqueObjectId>)
|
||||
timestampMs: number, // when the message was published, in ms since epoch
|
||||
topic: string, // the topic the message was published on
|
||||
data: T, // the arbitrary message data. Must be serializable and a valid argument to 'structuredClone()'
|
||||
};
|
||||
```
|
||||
|
||||
#### IPC Notes
|
||||
|
||||
There are some important things to keep in mind when using Appium's IPC feature:
|
||||
|
||||
- IPC is only available once `onIpcInit` has been called, at the end of the `createSession` flow.
|
||||
It cannot be used statically or in `createSession` hooks
|
||||
- In sum, IPC is only for use during a session (this is also to prevent drivers/plugins from
|
||||
accessing or reading data sent on IPC channels in other sessions.)
|
||||
- The default max size of an IPC message is 1MB. This can be configured by the server-admin by
|
||||
using the `--max-ipc-data-size` arg (value is a number in bytes).
|
||||
- If a message exceeds the configured size, any call to `publish` methods will throw, so be
|
||||
sure to cover this case in your error handling.
|
||||
- The default max number of IPC topics per session is 1000. This can be configured by the
|
||||
server-admin using the `--max-ipc-topics` arg.
|
||||
- If the topic limit is reached, calls to `subscribe` or `publish` on a new topic will throw, so
|
||||
be sure to cover this case in your error handling.
|
||||
- Topic names exist within a global namespace per session. So if you don't want to clash with other
|
||||
drivers or plugins, make sure you prefix your topic names with something unique, akin to vendor
|
||||
prefixes in the WebDriver standard (for example: `fake-driver:some-topic`). We recommend the
|
||||
format `<namespace>:<topic>`.
|
||||
|
||||
To see examples of IPC in action, check out Appium's own
|
||||
[FakeDriver](https://github.com/appium/appium/blob/master/packages/fake-driver/lib/driver.ts) and
|
||||
[FakePlugin](https://github.com/appium/appium/blob/master/packages/fake-plugin/lib/plugin.ts)
|
||||
extensions, which showcase several ways of using IPC messages.
|
||||
|
||||
@@ -518,3 +518,12 @@ async onUnexpectedShutdown(driver, cause) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Send messages to the driver or other plugins running on the same session
|
||||
|
||||
Even though drivers and plugins don't know anything about each other, it's possible for them to
|
||||
send messages that other drivers or plugins can listen for, within the context of the same session,
|
||||
using an IPC channel. Given that the developer instructions for this feature are the same for
|
||||
drivers and plugins, please head over to the IPC development docs for
|
||||
drivers at the driver
|
||||
development guide.
|
||||
|
||||
@@ -29,7 +29,7 @@ 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
|
||||
will call into `lib/bootstrap/config-file.js` to load and/or search for a configuration file and in
|
||||
`package.json`.
|
||||
|
||||
!!! note
|
||||
@@ -72,7 +72,7 @@ It is more straightforward to explain how config files are validated, so we'll s
|
||||
|
||||
### Validating Config Files
|
||||
|
||||
When a config file is found (`lib/config-file.js`), it will call the `validate` function exported
|
||||
When a config file is found (`lib/bootstrap/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.
|
||||
|
||||
|
||||
@@ -21,6 +21,48 @@ Appium has a graphical client which can be used to inspect application screensho
|
||||
application hierarchy, search for elements, run Appium commands, record app interactions, and more.
|
||||
It can be very useful for Appium test development.
|
||||
|
||||
\=== "Install as an Appium Plugin"
|
||||
|
||||
````
|
||||
```bash
|
||||
appium plugin install inspector
|
||||
```
|
||||
````
|
||||
|
||||
\=== "Install Standalone"
|
||||
|
||||
```
|
||||
Download the app from the Appium Inspector repo's [GitHub Releases section](https://github.com/appium/appium-inspector/releases).
|
||||
```
|
||||
|
||||
### [Appium MCP](https://github.com/appium/appium-mcp)
|
||||
|
||||
Appium MCP is a Model Context Protocol (MCP) server that provides mobile test development and
|
||||
automation capabilities using Appium.
|
||||
|
||||
```json title="Install This Tool"
|
||||
// Add the following to your MCP client configuration
|
||||
{
|
||||
"appium-mcp": {
|
||||
"disabled": false,
|
||||
"timeout": 100,
|
||||
"type": "stdio",
|
||||
"command": "npx",
|
||||
"args": ["appium-mcp@latest"],
|
||||
"env": {
|
||||
"ANDROID_HOME": "/path/to/android/sdk"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### [Skills](https://github.com/appium/skills)
|
||||
|
||||
A set of AI Agent skills to support Appium automation, for example:
|
||||
|
||||
- Help preparing Appium test environment from scratch, including common driver setup
|
||||
- Help preparing XCUITest driver and WebDriverAgent for real device automation
|
||||
|
||||
## Extension Tools
|
||||
|
||||
Appium driver or plugin developers can choose to include these tools in their driver/plugin:
|
||||
@@ -35,7 +77,7 @@ details needed for the driver/plugin have been set up correctly. The tool can be
|
||||
appium {driver|plugin} doctor <extension-name>
|
||||
```
|
||||
|
||||
It shows no results if the driver/plugin author did not implement Doctor support.
|
||||
It shows no results if the driver/plugin does not have such validation checks.
|
||||
|
||||
!!! note
|
||||
|
||||
@@ -48,6 +90,18 @@ out the documentation on [Building Doctor Checks](../developing/build-doctor-che
|
||||
|
||||
These tools are not maintained by the Appium team:
|
||||
|
||||
### [AppClaw](https://github.com/AppiumTestDistribution/AppClaw)
|
||||
|
||||
AppClaw is a CLI-based agentic AI layer for mobile automation, powered by [Appium MCP](#appium-mcp).
|
||||
Agent instructions can be passed directly via CLI, or defined as YAML flows in either structured
|
||||
or natural language syntax.
|
||||
|
||||
Supported by: `@AppiumTestDistribution`
|
||||
|
||||
```sh title="Install This Tool"
|
||||
npm install -g appclaw
|
||||
```
|
||||
|
||||
### [Appium Installer](https://github.com/AppiumTestDistribution/appium-installer)
|
||||
|
||||
Appium Installer is a command-line tool for simplifying setups of new Appium test environments.
|
||||
@@ -59,29 +113,3 @@ Supported by: `@AppiumTestDistribution`
|
||||
```sh title="Install This Tool"
|
||||
npm install -g appium-installer
|
||||
```
|
||||
|
||||
### [Jarvis Appium](https://github.com/AppiumTestDistribution/mcp-appium)
|
||||
|
||||
Jarvis Appium is a Model Context Protocol (MCP) server that provides mobile test development and
|
||||
automation capabilities using Appium.
|
||||
|
||||
Supported by: `@AppiumTestDistribution`
|
||||
|
||||
```json title="Install This Tool"
|
||||
// Add the following to your MCP client configuration
|
||||
{
|
||||
"mcpServers": {
|
||||
"jarvis-appium": {
|
||||
"disabled": false,
|
||||
"timeout": 100,
|
||||
"type": "stdio",
|
||||
"command": "npx",
|
||||
"args": ["jarvis-appium"],
|
||||
"env": {
|
||||
"ANDROID_HOME": "/path/to/android/sdk",
|
||||
"CAPABILITIES_CONFIG": "/path/to/your/capabilities.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
title: Session Capabilities
|
||||
---
|
||||
|
||||
"Capabilities" is the name given to the set of parameters used to start an Appium session. The
|
||||
information in the set describes what sort of "capabilities" you want your session to have, for
|
||||
example, a certain mobile operating system or a certain version of a device. Capabilities are
|
||||
represented as key-value pairs, with values allowed to be any valid JSON type, including
|
||||
other objects.
|
||||
Capabilities are the core parameters used to start an Appium session. They describe various
|
||||
features that you want your session to have, for example, a certain mobile operating system or a
|
||||
certain version of a device. Capabilities are represented as key-value pairs, with values allowed
|
||||
to be any valid JSON type, including other objects. Most importantly, they cannot be changed
|
||||
during the lifecycle of the session.
|
||||
|
||||
The W3C WebDriver spec's [section on Capabilities](https://w3c.github.io/webdriver/#capabilities)
|
||||
identifies a small set of 10 standard capabilities, including the following:
|
||||
The capabilities used in Appium follow [the W3C WebDriver specification of the same name](https://w3c.github.io/webdriver/#capabilities).
|
||||
The WebDriver spec defines a small set of standard capabilities, including the following:
|
||||
|
||||
| Capability Name | Type | Description |
|
||||
| ---------------- | -------- | ---------------------------------------------- |
|
||||
@@ -17,68 +17,64 @@ identifies a small set of 10 standard capabilities, including the following:
|
||||
| `browserVersion` | `string` | The specific version of the browser |
|
||||
| `platformName` | `string` | The type of platform hosting the browser |
|
||||
|
||||
While the above capabilities are commonly used by Appium drivers, they are not sufficient for
|
||||
describing Appium-specific features, such as the name of the driver to use, or the name of the app
|
||||
to launch. In order to achieve this, Appium defines its own [extension capabilities](https://w3c.github.io/webdriver/#dfn-extension-capability).
|
||||
|
||||
## Common Appium Capabilities
|
||||
|
||||
Appium understands these browser-focused capabilities, but introduces a number of additional
|
||||
capabilities. According to the WebDriver spec, any
|
||||
non-standard "extension capabilities" must include a namespace prefix (signifying the vendor
|
||||
introducing the capability), ending in a `:`. Appium's vendor prefix is
|
||||
`appium:`, and so any Appium-specific capabilities must include this prefix. Depending on which
|
||||
client you are using, the prefix may be added automatically or in conjunction with certain
|
||||
interfaces, but it is always a good practice to explicitly include it for clarity.
|
||||
According to the WebDriver spec, extension capabilities must include a namespace prefix (signifying
|
||||
the vendor introducing the capability), and the namespace must end a colon (`:`). Appium's vendor
|
||||
prefix is `appium:`, and so any Appium-specific capabilities must include this prefix. Depending on
|
||||
your Appium client, the prefix may be added automatically or in conjunction with certain interfaces,
|
||||
but it is always a good practice to explicitly include it for clarity.
|
||||
|
||||
Here is a list of all the globally-recognized Appium capabilities:
|
||||
Here are a few commonly (but not universally!) used Appium-specific capabilities:
|
||||
|
||||
!!! info
|
||||
| Capability Name | Type | Description |
|
||||
| ----------------------- | -------- | --------------------------------------------------------------- |
|
||||
| `appium:automationName` | `string` | The name of the Appium driver to use |
|
||||
| `appium:udid` | `string` | The unique device identifier of a particular device to automate |
|
||||
| `appium:app` | `string` | The path to an installable application |
|
||||
|
||||
```
|
||||
Individual drivers and plugins can support other capabilities, so refer to their documentation
|
||||
for lists of specific capability names. Some drivers may also not support all of these capabilities
|
||||
```
|
||||
All capabilities recognized by the Appium base driver (inherited by all drivers) can be found in the
|
||||
[Capabilities Reference document](../reference/session/caps.md). While this common capability set
|
||||
is fairly small, it can be greatly extended by Appium drivers and plugins, who can (and should)
|
||||
define their own capabilities. Make sure to reference their documentation to learn more about the
|
||||
capabilities they support. You can find a list of known drivers in the [Ecosystem Drivers](../ecosystem/drivers.md) document.
|
||||
|
||||
| <div style="width:12em">Capability</div> | Type | Required? | Description |
|
||||
| ---------------------------------------- | --------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `platformName` | `string` | yes | The type of platform hosting the app or browser |
|
||||
| `appium:automationName` | `string` | yes | The name of the Appium driver to use |
|
||||
| `browserName` | `string` | no | The name of the browser to launch and automate, if the driver supports web browsers as a special case |
|
||||
| `appium:app` | `string` | no | The path to an installable application |
|
||||
| `appium:deviceName` | `string` | no | The name of a particular device to automate, e.g., `iPhone 14` (currently only actually useful for specifying iOS simulators, since in other situations it's typically recommended to use a specific device id via the `appium:udid` capability). |
|
||||
| `appium:platformVersion` | `string` | no | The version of a platform, e.g., for iOS, `16.0` |
|
||||
| `appium:newCommandTimeout` | `number` | no | The number of seconds the Appium server should wait for clients to send commands before deciding that the client has gone away and the session should shut down. `60` seconds by default. Setting it to zero disables the timer. |
|
||||
| `appium:noReset` | `boolean` | no | If true, instruct an Appium driver to avoid its usual reset logic during session start and cleanup (default `false`) |
|
||||
| `appium:fullReset` | `boolean` | no | If true, instruct an Appium driver to augment its usual reset logic with additional steps to ensure maximum environmental reproducibility (default `false`) |
|
||||
| `appium:eventTimings` | `boolean` | no | If true, instruct an Appium driver to collect [Event Timings](./event-timing.md) (default `false`) |
|
||||
| `appium:printPageSourceOnFindFailure` | `boolean` | no | If true, collect the page source and print it to the Appium log whenever a request to find an element fails (default `false`) |
|
||||
Drivers are also able to place more complex constraints on capabilities as a group. For example,
|
||||
the XCUITest driver recommends that at least one of `browserName`, `appium:app`, or `appium:bundleId`
|
||||
is included in the capabilities, otherwise it will not be able to auto-install or auto-launch any
|
||||
application. Each driver will document how it interprets these capabilities and any other
|
||||
platform-specific requirements.
|
||||
|
||||
Some drivers place more complex constraints on capabilities as a group. For example, while the
|
||||
`appium:app` and `browserName` capabilities are listed above as optional, if you want to launch
|
||||
a session with a specific app, the XCUITest driver requires that at least one of `appium:app`,
|
||||
`browserName`, or `appium:bundleId` are included in the capabilities (otherwise it will not know
|
||||
what app to install and/or launch and will simply open a session on the home screen). Each driver
|
||||
will document how it interprets these capabilities and any other platform-specific requirements.
|
||||
The way to construct capabilities and start a session will likely differ depending on your Appium
|
||||
client. For examples of doing this in each client library, head to the [Ecosystem Clients](../ecosystem/clients.md)
|
||||
page and click through to the appropriate client documentation.
|
||||
|
||||
!!! note
|
||||
|
||||
```
|
||||
Capabilities are like parameters used when starting a session. After the capabilities are sent
|
||||
and the session is started, they cannot be changed. If a driver supports updating aspects of
|
||||
its behaviour in the course of a session, it will provide a [Setting](./settings.md) for this
|
||||
purpose instead of, or in addition to, a capability.
|
||||
Once your capabilities are sent to the server and the session is started, they cannot be
|
||||
changed. If a driver supports updating its behaviour during a session, it will use the
|
||||
[Settings API](./settings.md) for this purpose.
|
||||
```
|
||||
|
||||
Each Appium client has its own way of constructing capabilities and starting a session. For
|
||||
examples of doing this in each client library, head to the [Ecosystem](../ecosystem/index.md) page
|
||||
and click through to the appropriate client documentation.
|
||||
|
||||
## BiDi Protocol Support
|
||||
|
||||
Appium supports [WebDriver BiDi](https://w3c.github.io/webdriver-bidi/) protocol since base–driver 9.5.0.
|
||||
The actual behavior depends on individual drivers while the Appium and the baseーdriver support the protocol.
|
||||
Please make sure if a driver supports the protocol and what kind of commands/events it supports in the documentation.
|
||||
In addition to the standard WebDriver protocol (now known as WebDriver Classic), Appium supports the
|
||||
[WebDriver BiDi](https://w3c.github.io/webdriver-bidi/) protocol. Support for this protocol is
|
||||
opt-in, and requires the use of the standard `webSocketUrl` capability.
|
||||
|
||||
| Capability Name | Type | Description |
|
||||
| --------------- | --------- | ------------------------------------------------------- |
|
||||
| `webSocketUrl` | `boolean` | To enable BiDi protocol in the session. |
|
||||
| Capability Name | Type | Description |
|
||||
| --------------- | --------- | ----------------------------------------------- |
|
||||
| `webSocketUrl` | `boolean` | Whether BiDi protocol is enabled in the session |
|
||||
|
||||
All BiDi commands supported by the Appium base driver (inherited by all drivers) can be found in the
|
||||
[BiDi Protocol API Reference document](../reference/api/bidi.md). Similarly to WebDriver Classic
|
||||
commands, individual Appium drivers and plugins can define their own supported standard and custom
|
||||
BiDi commands, so make sure to reference their documentation.
|
||||
|
||||
## Using `appium:options` to Group Capabilities
|
||||
|
||||
@@ -124,8 +120,7 @@ creates in response to a new session request. This is through the concept of "al
|
||||
!!! note
|
||||
|
||||
```
|
||||
Check out the [spec itself](https://w3c.github.io/webdriver/#processing-capabilities) or
|
||||
a [summarized version](https://github.com/jlipps/simple-wd-spec#processing-capabilities) for
|
||||
Check out the [spec itself](https://w3c.github.io/webdriver/#processing-capabilities) for
|
||||
a more in-depth description of how capabilities are processed.
|
||||
```
|
||||
|
||||
|
||||
@@ -98,5 +98,5 @@ The above configuration corresponds to the `--driver-xcuitest-webkit-debug-proxy
|
||||
```
|
||||
|
||||
All properties are case-sensitive and will be in
|
||||
[kebab-case](https://en.wikipedia.org/wiki/Naming_convention_\(programming\)#Delimiter-separated_words).
|
||||
[kebab-case](https://en.wikipedia.org/wiki/Naming_convention_(programming)#Delimiter-separated_words).
|
||||
For example, `callback-port` is allowed, but `callbackPort` is not.
|
||||
|
||||
@@ -3,27 +3,27 @@ title: Appium Server Security
|
||||
---
|
||||
|
||||
The Appium team makes every effort to ensure the security of the Appium server. This is especially
|
||||
important when Appium is run in a multitenant environment, or when multiple users are running
|
||||
sessions on the same Appium server. In general, you can only safely enable all of Appium's features if
|
||||
all the following are true:
|
||||
important when Appium is run in a multi-tenant environment, or when multiple users are running
|
||||
sessions on the same Appium server. To ensure a safe environment for Appium's purposes, all of the
|
||||
following should be true:
|
||||
|
||||
- You're running your own Appium server locally or within a protected internal network
|
||||
- You're not sharing it with any untrusted parties
|
||||
- You don't expose Appium's port(s) to the wider internet
|
||||
|
||||
But because many Appium users might not be able to guarantee such a safe environment, the Appium
|
||||
team puts many features behind a security protection mechanism, which forces system admins (the
|
||||
people who are in charge of starting the Appium server) to _explicitly opt-in_ to these features.
|
||||
(Third-party driver and plugin authors can also hide behaviour behind security
|
||||
flags.)
|
||||
But because not all Appium hosts can guarantee such a safe environment, certain insecure Appium
|
||||
features are disabled by default, and require explicit opt-in in order to enable them. Most
|
||||
importantly, this can _only_ be done by the Appium server _host_, and Appium _client_ sessions are
|
||||
not allowed to change this.
|
||||
|
||||
For security reasons, Appium client sessions can _not_ request feature enablement via capabilities.
|
||||
This is the responsibility of the server admin who configures and launches the Appium server.
|
||||
While it is possible for an Appium host to simply enable all insecure features at once, each
|
||||
feature also has a unique name, which can be used for granular control over the server state.
|
||||
|
||||
## Security Server Args
|
||||
|
||||
The [Server CLI](../reference/cli/server.md) doc outlines three relevant arguments which may be passed to
|
||||
Appium, when starting it from the command line:
|
||||
Enabling or disabling insecure features is done via [Appium server launch arguments](../reference/cli/server.md)
|
||||
or [configuration file](./config.md). The former document outlines three relevant arguments for
|
||||
achieving this:
|
||||
|
||||
| <div style="width:10em">Parameter</div> | Description |
|
||||
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
@@ -31,36 +31,30 @@ Appium, when starting it from the command line:
|
||||
| `--allow-insecure` | Turns on _only_ specified features, except those blocked by `--deny-insecure`. Has no effect when used in combination with `--relaxed-security` |
|
||||
| `--deny-insecure` | Explicitly turns _off_ specified features, overriding `--relaxed-security` and `--allow-insecure` |
|
||||
|
||||
All of the above arguments can also be specified in the [Appium Configuration file](./config.md).
|
||||
|
||||
Features passed to `--allow-insecure`/`--deny-insecure` must be specified as a comma-separated list,
|
||||
and each feature in the list must additionally include a prefix, indicating the driver to which the
|
||||
feature should apply. The prefix can be either the driver's `automationName`, or the wildcard (`*`)
|
||||
symbol, if the feature should be applied to all drivers. The prefix and feature name are separated
|
||||
using the colon character (`:`).
|
||||
and each feature in the list must additionally include a prefix, indicating the driver to whose
|
||||
sessions the feature should apply. The prefix can be either the driver's `automationName`, or the
|
||||
wildcard (`*`) symbol, if the feature should be applied to all drivers. The prefix and feature name
|
||||
are separated using the colon character (`:`).
|
||||
|
||||
For example, `first:foo` refers to the `foo` feature for the `first` driver, whereas `*:bar` refers
|
||||
to the `bar` feature for all drivers.
|
||||
|
||||
## Insecure Features
|
||||
|
||||
Each Appium driver is responsible for its own security, and can create its own feature names. Thus,
|
||||
you should read through the documentation for a particular driver to know which feature names it
|
||||
might use. Here is an incomplete list of examples from some of Appium's official drivers:
|
||||
Almost all insecure features are defined on a per-driver or plugin basis, so make sure to read the
|
||||
documentation for a particular driver/plugin to know which feature names it might use.
|
||||
|
||||
| <div style="width:12em">Feature Name</div> | Description | Supported Extension(s) |
|
||||
| ------------------------------------------ | --------------------------------------------------------------------------------------- | ---------------------------------------------- |
|
||||
| `get_server_logs` | Allows retrieving of Appium server logs via the Webdriver log interface | IOS, XCUITest, Android, UiAutomator2, Espresso |
|
||||
| `adb_shell` | Allows execution of arbitrary shell commands via ADB, using the `mobile: shell` command | Android, UiAutomator2, Espresso |
|
||||
| `record_audio` | Allow recording of host machine audio inputs | XCUITest |
|
||||
| `execute_driver_script` | Allows sending a request that has multiple Appium commands. | Execute Driver Plugin |
|
||||
Certain insecure features are also defined on the Appium server itself. For a list of these
|
||||
features, as well as the features defined in official plugins, see
|
||||
[the Insecure Features CLI Reference](../reference/cli/insecure-features.md) doc.
|
||||
|
||||
Some insecure features operate on the server level and do not require a driver session. Enabling
|
||||
these features require using the wildcard prefix:
|
||||
!!! note
|
||||
|
||||
| <div style="width:12em">Feature Name</div> | Description |
|
||||
| ------------------------------------------ | ------------------------------------------------------------------------------- |
|
||||
| `session_discovery` | Allows retrieving the list of active server sessions via `GET /appium/sessions` |
|
||||
```
|
||||
If you are a driver or plugin author and want to implement insecure features of your own, check
|
||||
out the [Building Drivers documentation](../developing/build-drivers.md#understand-server-assigned-driver-properties-and-security-flags).
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
hide:
|
||||
- 导航栏
|
||||
- navigation
|
||||
- toc
|
||||
|
||||
title: 欢迎使用
|
||||
@@ -29,9 +29,9 @@ title: 欢迎使用
|
||||
</a>
|
||||
</div>
|
||||
<div class="homepageSponsor">
|
||||
<a href="https://lambdatest.com/?utm_source=appium.io&utm_medium=organic&utm_campaign=june_25&utm_term=sk&utm_content=webpage">
|
||||
<img src="assets/images/sponsor-logo-lambdatest-dark.png#only-dark" style="width: 220px;" />
|
||||
<img src="assets/images/sponsor-logo-lambdatest-light.png#only-light" style="width: 220px;" />
|
||||
<a href="https://www.testmuai.com">
|
||||
<img src="assets/images/sponsor-logo-testmuai-dark.png#only-dark" style="width: 220px;" />
|
||||
<img src="assets/images/sponsor-logo-testmuai-light.png#only-light" style="width: 220px;" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
---
|
||||
title: Intro to Appium Drivers
|
||||
title: Appium 驱动程序介绍
|
||||
---
|
||||
|
||||
As the [main Overview](./appium.md) makes clear, "drivers" are basically Appium's answer to the
|
||||
question, "how do we support automation of multiple, unrelated platforms?" In this doc we'll get
|
||||
into a little more detail about how drivers work. The specific details of how drivers work probably
|
||||
don't matter too much for you, unless you're planning on writing your own driver or contributing to
|
||||
an existing driver (things we hope you do!).
|
||||
正如[概览](./appium.md)所阐明的那样,"驱动程序"基本上是 Appium 对"我们如何支持多个不相关平台的自动化?"这一问题的答案。 在本文档中,我们将更详细地了解驱动程序的工作原理。 驱动程序工作的具体细节对你来说可能并不那么重要,除非你打算编写自己的驱动程序或为现有驱动程序做贡献(我们希望你这样做!)。
|
||||
|
||||
The main benefit in understanding a bit more of how drivers work is that being aware of the typical
|
||||
complexity or the typical driver architecture will inform your debugging process when you
|
||||
inevitably run into an issue in one of your tests.
|
||||
了解更多驱动程序工作原理的主要好处是,了解典型的复杂性或典型的驱动程序架构将有助于你在测试中遇到问题时进行调试。
|
||||
|
||||
## Interface Implementations
|
||||
## 接口实现
|
||||
|
||||
At the most basic level, drivers are simply Node.js classes that extend a special class included in
|
||||
Appium, called `BaseDriver`. You could have something very close to a "working" driver, with these
|
||||
very simple lines of code:
|
||||
在最基本的层面上,驱动程序只是扩展了 Appium 中包含的一个特殊类的 Node.js 类,这个类叫做 `BaseDriver`。 你可以用以下非常简单的几行代码就拥有一个非常接近"可工作"的驱动程序:
|
||||
|
||||
```js
|
||||
import BaseDriver from '@appium/base-driver'
|
||||
@@ -25,21 +17,11 @@ class MyNewDriver extends BaseDriver {
|
||||
}
|
||||
```
|
||||
|
||||
This empty driver doesn't _do_ anything, but you could wrap it up in a Node.js module, add a few
|
||||
Appium-related fields to the module's manifest (`package.json`), and then install it using `appium
|
||||
driver install`.
|
||||
这个空驱动程序不会_做_任何事情,但你可以将它打包成一个 Node.js 模块,在模块的清单文件(`package.json`)中添加一些与 Appium 相关的字段,然后使用 `appium driver install` 安装它。
|
||||
|
||||
So, from a technical perspective, an Appium driver is just a bit of code that inherits from some
|
||||
other Appium code. That's it! Now, inheriting from `BaseDriver` actually gives us a lot, because
|
||||
`BaseDriver` is essentially an encapsulation of the entire WebDriver protocol. So all a driver
|
||||
needs to do something useful is to _implement_ Node.js methods with names corresponding to
|
||||
their WebDriver protocol equivalents.
|
||||
因此,从技术角度来看,Appium 驱动程序只是一些继承自其他 Appium 代码的代码。 就是这样! 现在,继承自 `BaseDriver` 实际上给了我们很多东西,因为 `BaseDriver` 本质上是整个 WebDriver 协议的封装。 所以驱动程序要做一些有用的事情,只需要_实现_名称与其 WebDriver 协议等效的 Node.js 方法。
|
||||
|
||||
So let's say I wanted to do something with this empty driver; first I have to decide which
|
||||
WebDriver command I want to implement. For our example, let's take the Navigate
|
||||
To WebDriver command. Leave aside for the moment
|
||||
what I want to have the driver _do_ when this command is executed. To tell Appium the driver can
|
||||
handle the command, all we have to do is define a method like this in our driver class:[^1]
|
||||
假设我想用这个空驱动程序做点什么;首先我必须决定要实现哪个 WebDriver 命令。 对于我们的例子,让我们选择[Navigate To](https://w3c.github.io/webdriver/#navigate-to) WebDriver 命令。 暂时不考虑当这个命令执行时我想让驱动程序_做_什么。 要告诉 Appium 驱动程序可以处理这个命令,我们所要做的就是在驱动程序类中定义一个像这样的方法:[^1]
|
||||
|
||||
```js
|
||||
async setUrl(url) {
|
||||
@@ -47,142 +29,73 @@ async setUrl(url) {
|
||||
}
|
||||
```
|
||||
|
||||
[^1]: You might notice that `setUrl` doesn't look anything like `Navigate To`, so how did we know
|
||||
to use it rather than some other random string? Well, Appium's WebDriver-protocol-to-method-name
|
||||
mapping is defined in a special file within the `@appium/base-driver` package called
|
||||
[routes.js](https://github.com/appium/appium/blob/master/packages/base-driver/lib/protocol/routes.js).
|
||||
So if you're writing a driver, this is where you would go to figure out what method names to use
|
||||
and what parameters to expect. Or you could look at the source for any of the main Appium
|
||||
drivers!
|
||||
[^1]: 你可能会注意到 `setUrl` 看起来与 `Navigate To` 完全不同,那么我们怎么知道使用它而不是其他随机字符串呢? 其实,Appium 的 WebDriver 协议到方法名的映射是在 `@appium/base-driver` 包中的一个特殊文件中定义的,叫做 [routes.js](https://github.com/appium/appium/blob/master/packages/base-driver/lib/protocol/routes.js)。
|
||||
所以如果你正在编写驱动程序,这就是你要去找出要使用什么方法名和期望什么参数的地方。 或者你可以查看任何主要 Appium 驱动程序的源代码!
|
||||
|
||||
That's it! How we actually implement the command is totally up to us, and depends on the
|
||||
platform(s) we want to support. Here are some different example implementations of this command for
|
||||
different platforms:
|
||||
就是这样! 我们如何实际实现该命令完全取决于我们自己,并取决于我们想要支持的平台。 以下是针对不同平台的此命令的一些不同示例实现:
|
||||
|
||||
- Browsers: execute some JavaScript to set `window.location.href`
|
||||
- iOS apps: launch an app using a deep link
|
||||
- Android apps: launch an app using a deep link
|
||||
- React apps: load a specific route
|
||||
- Unity: go to a named scene
|
||||
- 浏览器:执行一些 JavaScript 来设置 `window.location.href`
|
||||
- iOS 应用:使用深度链接启动应用
|
||||
- Android 应用:使用深度链接启动应用
|
||||
- React 应用:加载特定路由
|
||||
- Unity:转到指定场景
|
||||
|
||||
So you can see there can be a lot of differences between how drivers implement the same WebDriver
|
||||
command across platforms.[^2] What is the _same_, though, is how they express that they can handle
|
||||
a protocol command.
|
||||
因此,你可以看到,不同平台上驱动程序实现相同 WebDriver 命令的方式可能存在很大差异。[^2] 然而,_相同_的是它们表达可以处理协议命令的方式。
|
||||
|
||||
[^2]: Of course, we want to keep the semantics as similar as possible, but in the world of iOS, for
|
||||
example, launching an app via a deep link (a URL with a special app-specific scheme) is about as
|
||||
close as we are going to get to navigating to a web URL.
|
||||
[^2]: 当然,我们希望保持语义尽可能相似,但在 iOS 的世界里,例如,通过深度链接(具有特殊应用特定方案的 URL)启动应用是我们最接近导航到 Web URL 的方式。
|
||||
|
||||
We're going into this great amount of detail (which you don't need to remember, by the way),
|
||||
because it's important to stress the point that an Appium driver is not inherently anything in
|
||||
particular, other than a bit of JS code that can handle WebDriver protocol commands. Where you go
|
||||
from there is up to you, the driver author!
|
||||
我们之所以如此详细地讨论(顺便说一下,你不需要记住这些),是因为重要的是要强调一点,Appium 驱动程序本质上不是任何特定的东西,只是一些可以处理 WebDriver 协议命令的 JS 代码。 从那里去哪里取决于你,驱动程序作者!
|
||||
|
||||
## Automation mapping
|
||||
## 自动化映射
|
||||
|
||||
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 驱动程序使用 Apple 的一项名为 [XCUITest](https://developer.apple.com/documentation/xctest/xcuielement) 的技术。 这些底层自动化技术通常都有自己专有或特殊的 API。 编写驱动程序就是将 WebDriver 协议映射到这个底层 API 的任务(有时是一组不同的底层 API——例如,UiAutomator2 驱动程序不仅依赖于 Google 的 [UiAutomator2](https://developer.android.com/training/testing/other-components/ui-automator) 技术,还依赖于只能通过 [ADB](https://developer.android.com/tools/adb) 获得的功能,以及只能通过辅助应用内的 Android SDK 获得的功能)。 将所有这些整合到一个单一、可用的 WebDriver 接口中,是驱动程序开发这项非常有用(但极具挑战性)的艺术!
|
||||
|
||||
## Multi-level architecture
|
||||
## 多层架构
|
||||
|
||||
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。
|
||||
- XCUITest 驱动程序做的事情远不止 WebDriverAgent 所能做的,例如使用模拟器或设备、安装应用等。
|
||||
|
||||
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 为例,我们同时使用以下一组技术:
|
||||
|
||||
- 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
|
||||
- 你的测试代码(使用其编程语言)- 由你拥有
|
||||
- Appium 客户端库 - 由 Appium 拥有
|
||||
- Selenium 客户端库 - 由 Selenium 拥有
|
||||
- 网络(本地或互联网)
|
||||
- Appium 服务器 - 由 Appium 拥有
|
||||
- Appium XCUITest 驱动程序 - 由 Appium 拥有
|
||||
- WebDriverAgent - 由 Appium 拥有
|
||||
- Xcode - 由 Apple 拥有
|
||||
- XCUITest - 由 Apple 拥有
|
||||
- iOS 本身 - 由 Apple 拥有
|
||||
- macOS(运行 Xcode 和 iOS 模拟器的地方)- 由 Apple 拥有
|
||||
|
||||
It's a pretty deep stack!
|
||||
这是一个相当深的技术栈!
|
||||
|
||||
## Proxy mode
|
||||
## 代理模式
|
||||
|
||||
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 服务器和 WebDriverAgent 服务器会生成不同的会话 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,196 +1,72 @@
|
||||
---
|
||||
title: Appium Project History
|
||||
title: Appium 项目历史
|
||||
---
|
||||
|
||||
Appium has been around in one form or another since 2012. It's been under the
|
||||
direction of various individuals and organizations, and it's even been
|
||||
implemented in 3 different programming languages! Welcome to more than you ever
|
||||
wanted to know about how Appium got to be what is it today...
|
||||
Appium 自 2012 年以来以某种形式存在。 它由不同的个人和组织指导,甚至用 3 种不同的编程语言实现过! 欢迎了解关于 Appium 如何发展到今天这个样子的更多信息……
|
||||
|
||||
## Early Inspiration
|
||||
## 早期灵感
|
||||
|
||||
[Dan Cuellar](https://twitter.com/thedancuellar) was the Test Manager at Zoosk
|
||||
in 2011, when he encountered a problem. The length of the test passes on the
|
||||
iOS product was getting out of hand. Less testing was an option, but would come
|
||||
with additional risk, especially with it taking several days to get patches
|
||||
through the iOS App Store Review process. He thought back to his days working
|
||||
on websites and realized automation was the answer.
|
||||
[Dan Cuellar](https://twitter.com/thedancuellar) 在 2011 年担任 Zoosk 的测试经理时遇到了一个问题。 iOS 产品的测试通过时间变得越来越长,难以控制。 减少测试是一个选择,但会带来额外的风险,特别是在通过 iOS App Store 审核流程获得补丁需要几天时间的情况下。 他回想起自己在网站上工作的日子,意识到自动化是答案。
|
||||
|
||||
Dan surveyed the existing landscape of tools, only to find that all of them
|
||||
hand major drawbacks. The tool supplied by Apple, UIAutomation, required tests
|
||||
to be written in JavaScript, and did not allow for real-time debugging or
|
||||
interpretation. It also had to be executed inside the Xcode profiling tool,
|
||||
Instruments. Other 3rd-party tools used private APIs and required SDKs and HTTP
|
||||
Servers to be embedded into the application. This seemed highly undesirable.
|
||||
Dan 调查了现有的工具格局,却发现它们都有重大缺陷。 Apple 提供的工具 UIAutomation 要求测试必须用 JavaScript 编写,并且不允许实时调试或解释。 它还必须在 Xcode 的性能分析工具 Instruments 中执行。 其他第三方工具使用私有 API,并要求将 SDK 和 HTTP 服务器嵌入到应用程序中。 这看起来非常不可取。
|
||||
|
||||
Unsatisfied with the existing options, Dan asked his manager for some
|
||||
additional time to see if he could find a better way. He spent 2 weeks poking
|
||||
and prodding around to see if there was a way to use approved Apple
|
||||
technologies to automate an iOS application. The first implementation he tried
|
||||
used AppleScript to send messages to Mac UI elements using the OS
|
||||
X accessibility APIs. This worked to some degree, but would never work on real
|
||||
devices, not to mention other drawbacks.
|
||||
对现有选项不满意,Dan 向他的经理要求一些额外的时间,看看他能否找到更好的方法。 他花了 2 周时间探索和试验,看看是否有办法使用 Apple 批准的技术来自动化 iOS 应用程序。 他尝试的第一个实现使用 AppleScript 通过 OS X 辅助功能 API 向 Mac UI 元素发送消息。 这在一定程度上有效,但永远无法在真实设备上工作,更不用说其他缺点了。
|
||||
|
||||
So he thought, what if I could get the UIAutomation framework to run in real
|
||||
time like an interpreter? He looked into it and he determined that all he would
|
||||
need to do is find a way to receive, execute, and reply to commands from within
|
||||
a UIAutomation javascript program. Using the utility Apple provided for
|
||||
executing shell commands he was able to `cat` sequentially ordered text files
|
||||
to receive commands, `eval()` the output to execute them, and write them back
|
||||
to disk with `python`. He then prepared code in C# that implemented the
|
||||
Selenium-style syntax to write the sequentially ordered javascript commands.
|
||||
iOSAuto is born.
|
||||
所以他想,如果我能让 UIAutomation 框架像解释器一样实时运行会怎样? 他研究了一下,确定他所需要做的就是找到一种方法在 UIAutomation JavaScript 程序中接收、执行和回复命令。 使用 Apple 提供的用于执行 shell 命令的实用程序,他能够 `cat` 顺序排列的文本文件来接收命令,`eval()` 输出以执行它们,并用 `python` 将它们写回磁盘。 然后他用 C# 准备了实现 Selenium 样式语法的代码来编写顺序排列的 JavaScript 命令。
|
||||
iOSAuto 诞生了。
|
||||
|
||||
## Selenium Conference 2012
|
||||
## 2012 年 Selenium 大会
|
||||
|
||||
Dan was selected to speak at Selenium Conference 2012 in London about an
|
||||
entirely different topic. As part of his presentation, he showed off iOS
|
||||
Automation using Selenium syntax to demonstrate writing platform-agnostic tests
|
||||
that use separate platform-specific page objects with a common interface. To
|
||||
his surprise, the cool test architecture would take a backseat to the spectacle
|
||||
of iOS tests running like WebDriver tests. Several people suggested that he
|
||||
give a lightning talk later in the conference to explain exactly how it worked.
|
||||
Dan 被选中在 2012 年伦敦 Selenium 大会上就一个完全不同的主题发表演讲。 作为他演讲的一部分,他展示了使用 Selenium 语法的 iOS 自动化,以演示编写平台无关的测试,这些测试使用具有通用接口的独立平台特定页面对象。 令他惊讶的是,酷炫的测试架构让 iOS 测试像 WebDriver 测试一样运行。 有几个人建议他稍后在会议上做一个闪电演讲来解释它是如何工作的。
|
||||
|
||||
On the second day of the conference, Dan stepped up on stage to give the
|
||||
lightning talk. Jason Huggins, co-creator of Selenium, moderated the lightning
|
||||
talks. Dan experienced technical difficulties getting his presentation to
|
||||
load, and Jason nearly had to move on to the next lightning talk. At the last
|
||||
moment, the screen turned on and Dan jumped into his presentation. He explained
|
||||
the details of his implementation and how it worked, begged for contributors,
|
||||
and in five minutes it was over. The crowd applauded politely, and he left the
|
||||
stage.
|
||||
在会议的第二天,Dan 走上舞台做闪电演讲。 Jason Huggins,Selenium 的共同创建者,主持了闪电演讲。 Dan 在加载演示文稿时遇到了技术困难,Jason 几乎不得不继续下一个闪电演讲。 在最后一刻,屏幕亮了,Dan 开始了他的演讲。 他解释了他的实现细节和工作原理,恳求贡献者,五分钟后就结束了。 观众礼貌地鼓掌,他离开了舞台。
|
||||
|
||||
## The Phone Rings
|
||||
## 电话响起
|
||||
|
||||
Four months after the Selenium Conference, Jason called Dan. Jason had been
|
||||
working on iOS testing support for a client at Sauce Labs. Jason remembered
|
||||
Dan's lightning talk and thought the project might be useful to Jason's work,
|
||||
but Dan's source code was not public. Jason asked Dan to meet up. Later that
|
||||
week, Dan met Jason in a bar in San Francisco and showed him the source code
|
||||
for iOS Auto.
|
||||
Selenium 大会四个月后,Jason 打电话给 Dan。 Jason 一直在 Sauce Labs 为客户开发 iOS 测试支持。 Jason 记得 Dan 的闪电演讲,认为这个项目可能对 Jason 的工作有用,但 Dan 的源代码没有公开。 Jason 要求 Dan 见面。 那周晚些时候,Dan 在旧金山的一家酒吧见到了 Jason,并向他展示了 iOS Auto 的源代码。
|
||||
|
||||
A long-time open source advocate, Jason encouraged Dan to release his code
|
||||
under an open source license. In August, Dan released the source
|
||||
code
|
||||
on GitHub in C#. Jason encouraged Dan to change the language to make the
|
||||
project more appealing to potential contributors. Dan uploaded a new version
|
||||
in
|
||||
Python.
|
||||
In September, Jason added a web server and began to implement the WebDriver
|
||||
wire
|
||||
protocol
|
||||
over HTTP, making iOS Auto scriptable from any Selenium WebDriver client
|
||||
library in any language.
|
||||
作为一个长期的开源倡导者,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),使 iOS Auto 可以从任何语言的任何 Selenium WebDriver 客户端库编写脚本。
|
||||
|
||||
## The Mobile Testing Summit
|
||||
## 移动测试峰会
|
||||
|
||||
Jason decided that the project should be presented at the Mobile Testing
|
||||
Summit in November, but suggested that the
|
||||
project get a new name first. Many ideas were thrown out and they settled on
|
||||
AppleCart. A day later, while he was perusing some of Apple's guidance on
|
||||
copyright and trademarks, Jason noticed that under the section of examples for
|
||||
names Apple would defend its trademarks against, the first example was
|
||||
"AppleCart". He called Dan and informed him of the situation, and they
|
||||
brainstormed for a bit before Jason hit the jackpot. Appium... Selenium for
|
||||
Apps.
|
||||
Jason 决定该项目应该在 11 月的[移动测试峰会](https://twitter.com/mobtestsummit)上展示,但建议项目首先改个新名字。 人们提出了许多想法,他们最终选定了 AppleCart。 一天后,当 Jason 浏览 Apple 关于版权和商标的一些指导时,他注意到在 Apple 会保护其商标的名称示例部分下,第一个例子是"AppleCart"。 他打电话给 Dan 并告知了情况,他们集思广益了一会儿,然后 Jason 中了大奖。 Appium…… 应用程序的 Selenium。
|
||||
|
||||
## Sauce Labs and Node.js
|
||||
## Sauce Labs 和 Node.js
|
||||
|
||||
In January 2013, not long after the Mobile Testing Summit, Sauce Labs decided
|
||||
to fully back Appium and provide more developer power. A task force was created
|
||||
to evaluate the current state and how best to move forward with the project.
|
||||
The team, which included Jonathan Lipps (the current project lead), decided
|
||||
that Appium needed a rebirth, and ultimately settled on Node.js as the
|
||||
framework to use. Node is well-known as a fast and efficient web server
|
||||
backend, and at the end of the day, Appium is just a highly-specialized web
|
||||
server. It was also decided that JavaScript as a language was accessible enough
|
||||
that Appium would be able to grow into a larger community of open-source
|
||||
developers with JavaScript than the other options on the table.
|
||||
2013 年 1 月,也就是移动测试峰会后不久,Sauce Labs 决定全力支持 Appium 并提供更多开发人员力量。 创建了一个工作组来评估当前状态以及如何最好地推进该项目。
|
||||
该团队包括 Jonathan Lipps(现任项目负责人),他们决定 Appium 需要重生,并最终选择 Node.js 作为使用的框架。 Node 以快速高效的 Web 服务器后端而闻名,而归根结底,Appium 只是一个高度专业化的 Web 服务器。 还决定将 JavaScript 作为一种语言足够易于访问,使得 Appium 能够发展成为一个比其他选项更大的开源开发者社区。
|
||||
|
||||
In just a few days, the team leveraged the existing work on Appium and had
|
||||
a new version of Appium with as much functionality as the previous Python
|
||||
version. The foundation had been laid for Appium's basic architecture, and we
|
||||
have been successfully building on it since. A few weeks into this sprint,
|
||||
Jonathan Lipps was formally designated project lead and he began to strategize
|
||||
how to get more people from the community involved with Appium's development.
|
||||
仅仅几天之内,团队就利用 Appium 的现有工作,创建了一个与之前 Python 版本功能相当的新版本 Appium。 为 Appium 的基本架构奠定了基础,从那时起我们一直在成功地构建它。 在这次冲刺开始几周后,Jonathan Lipps 被正式指定为项目负责人,他开始制定战略,如何让更多来自社区的人参与 Appium 的开发。
|
||||
|
||||
## Appium Around the World
|
||||
## Appium 走向世界
|
||||
|
||||
Ultimately, Jonathan decided that getting Appium in front of as many developers
|
||||
at conferences and meetups was the best way to attract users and contributions.
|
||||
Appium in its new incarnation was debuted at the Google Test Automation
|
||||
Conference 2013. Later in 2013,
|
||||
Appium was presented at conferences and meetups all around the US, as well as
|
||||
in England, Poland, Portugal, and Australia. Notably, Jonathan had Appium
|
||||
[perform as instruments in a band](https://www.youtube.com/watch?v=zsbNVkayYRQ)
|
||||
and Dan Cuellar put together a fun Appium video
|
||||
montage for Selenium Conference.
|
||||
最终,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)。
|
||||
|
||||
But during all these presentations and conferences, the project continued to
|
||||
develop. Early in 2013 we released Android and Selendroid support, making
|
||||
Appium the first truly cross-platform automation framework. The project also
|
||||
continued to attract users and contributors, and by the end of 2013, we'd
|
||||
already had well over 1,000 commits.
|
||||
在所有这些演讲和会议期间,项目继续发展。 2013 年初,我们发布了 Android 和 Selendroid 支持,使 Appium 成为第一个真正的跨平台自动化框架。 该项目还继续吸引用户和贡献者,到 2013 年底,我们已经有超过 1,000 次提交。
|
||||
|
||||
## The Road to Appium 1.0
|
||||
## 通往 Appium 1.0 之路
|
||||
|
||||
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](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
|
||||
on Appium, but the entire community stayed involved in guiding the project and
|
||||
contributing to it, and project governance continued to happen in the open, on
|
||||
public mailing lists and GitHub's issue tracker.
|
||||
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 的问题跟踪器上进行。
|
||||
|
||||
## The Appium Umbrella Broadens
|
||||
## Appium 扩大
|
||||
|
||||
Eventually, it became clear that the Appium codebase was not optimized for
|
||||
a large team of distributed, sometime contributors. We took the opportunity as
|
||||
a committer team to rewrite Appium from the ground up, using a more modern
|
||||
version of the JavaScript language, and redoing Appium's architecture so that
|
||||
it was easy for users or third-party developers to build their own Appium
|
||||
"drivers". We wanted for it to be easier for new contributors to get ramped up
|
||||
on the Appium codebase, and to see support for new platforms added to Appium by
|
||||
groups other than the core team. That vision has begun to be fulfilled, with
|
||||
groups like Microsoft and Youi.tv adding drivers to Appium for Windows desktop
|
||||
app automation and Youi.tv app automation, respectively.
|
||||
最终,很明显 Appium 代码库没有针对大型分布式团队的兼职贡献者进行优化。 作为提交者团队,我们借此机会从头开始重写 Appium,使用更现代的 JavaScript 语言版本,并重做 Appium 的架构,使用户或第三方开发者可以轻松构建自己的 Appium"驱动程序"。 我们希望新贡献者更容易熟悉 Appium 代码库,并看到核心团队以外的团队为 Appium 添加对新平台的支持。 这一愿景已经开始实现,微软和 Youi.tv 等团体分别为 Windows 桌面应用程序自动化和 Youi.tv 应用程序自动化向 Appium 添加了驱动程序。
|
||||
|
||||
## Appium To The People
|
||||
## Appium 献给人民
|
||||
|
||||
In late 2016, Sauce Labs donated Appium as a project to the JS
|
||||
Foundation, in order to cement for the world Sauce's
|
||||
commitment that Appium remains open source. The JS Foundation is a non-profit
|
||||
open source stewardship organization which takes responsibility for holding the
|
||||
copyright for open source projects, as well as ensuring they have a long and
|
||||
successful tenure in the community. As a result of our move to a non-profit
|
||||
foundation, we hope that the door will open even more widely for new
|
||||
contributors, either as individuals or representing one of the many companies
|
||||
which now have an interest in seeing Appium move forward.
|
||||
2016 年底,Sauce Labs 将 Appium 作为一个项目捐赠给 [JS 基金会](https://js.foundation),以便向世界证明 Sauce 承诺 Appium 保持开源。 JS 基金会是一个非营利性开源管理组织,负责持有开源项目的版权,并确保它们在社区中拥有长久和成功的任期。 由于我们转移到非营利基金会,我们希望新贡献者的大门会更加敞开,无论是作为个人还是代表现在对 Appium 前进有兴趣的众多公司之一。
|
||||
|
||||
Eventually, the JS Foundation merged into the [OpenJS Foundation](https://openjsf.org),
|
||||
and Appium became an Impact Project in the foundation.
|
||||
最终,JS 基金会并入了 [OpenJS 基金会](https://openjsf.org),Appium 成为该基金会的影响力项目。
|
||||
|
||||
## Appium 2.0
|
||||
|
||||
Appium 2 was released in 2023 and introduced an entirely revamped architecture, shifting focus to Appium
|
||||
as an ecosystem rather than an all-in-one project. This unlocked the ability for anyone to develop
|
||||
and share their own Appium extensions (drivers and plugins), opening up a world of possibilities
|
||||
for automation-related development for platforms far beyond iOS and Android! As a result,
|
||||
many third-party extensions were created, such as new drivers for Flutter and Windows, plugins for
|
||||
mocking APIs and managing device farms, new Appium clients based on Rust and Swift, and much more.
|
||||
Appium 2 于 2023 年发布,引入了一个全新的架构,将重点从一体化项目转移到作为生态系统的 Appium。 这为任何人开发和共享自己的 Appium 扩展(驱动程序和插件)开辟了可能性,为远超 iOS 和 Android 的平台的自动化相关开发打开了一个充满可能性的世界! 因此,创建了许多第三方扩展,例如用于 Flutter 和 Windows 的新驱动程序、用于模拟 API 和管理设备农场的插件、基于 Rust 和 Swift 的新 Appium 客户端等等。
|
||||
|
||||
Around this time was also when we started a sponsorship program for Appium, which attracted various
|
||||
major and minor sponsors alike. This allowed us to give back to the Appium community, by compensating
|
||||
contributors for their voluntary work on the project.
|
||||
大约在这个时候,我们还启动了 Appium 的赞助计划,吸引了各种大小赞助商。 这使我们能够回馈 Appium 社区,为贡献者在项目上的志愿工作提供补偿。
|
||||
|
||||
## Appium 3.0
|
||||
|
||||
2025 saw the release of Appium 3. This update was a lot smaller than Appium 2 and included only a
|
||||
few behavioral changes, instead focusing on removing deprecated code and updating compatibility for
|
||||
more modern ecosystems. Still, this reduced scope was also to be expected: since Appium 2, the
|
||||
main feature development efforts had shifted to individual drivers and plugins, many of which had
|
||||
gone through multiple major updates during the Appium 2 era.
|
||||
2025 年看到了 Appium 3 的发布。 这次更新比 Appium 2 小得多,只包括一些行为变化,而是专注于删除已弃用的代码并更新对更现代生态系统的兼容性。 尽管如此,这种缩小的范围也是意料之中的:自 Appium 2 以来,主要功能开发工作已转移到各个驱动程序和插件,其中许多在 Appium 2 时代经历了多次重大更新。
|
||||
|
||||
@@ -2,38 +2,35 @@
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Appium in a Nutshell
|
||||
title: Appium 概览
|
||||
---
|
||||
|
||||
As mentioned on the main page, Appium aims to support UI automation of many _different platforms_
|
||||
(mobile, web, desktop, etc.). Not only that, but it also aims to support automation code written in
|
||||
_different languages_ (JS, Java, Python, etc.). Combining all of this functionality in a single
|
||||
program is a very daunting, if not impossible task!
|
||||
如主页所述,Appium 旨在支持_多个不同平台_(移动端、Web、桌面等)的 UI 自动化。 不仅如此,它还旨在支持用_不同语言_(JS、Java、Python 等)编写的自动化代码。 将所有这些功能整合到一个程序中是一项非常艰巨的任务,甚至可以说是不可能完成的任务!
|
||||
|
||||
In order to achieve this, Appium is effectively split into four parts:
|
||||
为了实现这一目标,Appium 实际上被分为四个部分:
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- :material-image-filter-center-focus-strong: **Appium Core** - defines the core APIs
|
||||
- :material-car: **Drivers** - implement connectivity to specific platforms
|
||||
- :octicons-code-16: **Clients** - implement Appium's API in specific languages
|
||||
- :fontawesome-solid-plug: **Plugins** - change or extend Appium's core functionality
|
||||
- :material-image-filter-center-focus-strong: **Appium 核心** - 定义核心 API
|
||||
- :material-car: **驱动程序** - 实现与特定平台的连接
|
||||
- :octicons-code-16: **客户端库** - 用特定语言实现 Appium 的 API
|
||||
- :fontawesome-solid-plug: **插件** - 改变或扩展 Appium 的核心功能
|
||||
|
||||
</div>
|
||||
|
||||
Therefore, in order to start automating something with Appium, you need to:
|
||||
因此,要开始使用 Appium 进行自动化,你需要:
|
||||
|
||||
- Install Appium itself
|
||||
- Install a driver for your target platform
|
||||
- Install a client library for your target programming language
|
||||
- (Optional) install one or more plugins
|
||||
- 安装 Appium 本身
|
||||
- 为你的目标平台安装驱动程序
|
||||
- 为你的目标编程语言安装客户端库
|
||||
- (可选)安装一个或多个插件
|
||||
|
||||
These are the basics! If you are ready to jump in, proceed with the [Quickstart](../quickstart/index.md)!
|
||||
这些就是基础知识! 如果你已经准备好开始,请继续阅读[快速入门](../quickstart/index.md)!
|
||||
|
||||
If you wish to learn more details about how it all works, see these pages for background material:
|
||||
如果你想了解更多关于其工作原理的详细信息,请参阅以下页面的背景材料:
|
||||
|
||||
- [Appium Core](./appium.md)
|
||||
- [Appium Drivers](./drivers.md)
|
||||
- [Appium Clients](./clients.md)
|
||||
- [Appium 核心](./appium.md)
|
||||
- [Appium 驱动程序](./drivers.md)
|
||||
- [Appium 客户端](./clients.md)
|
||||
|
||||
Finally, to learn about the origins of Appium, check out the [Appium Project History](./history.md).
|
||||
最后,要了解 Appium 的起源,请查看 [Appium 项目历史](./history.md)。
|
||||
|
||||
@@ -397,6 +397,45 @@ Deletes the virtual sensor with the type identified by `:sensorType`.
|
||||
|
||||
`null`
|
||||
|
||||
## Global Privacy Control Protocol
|
||||
|
||||
The [Global Privacy Control protocol](https://www.w3.org/TR/gpc) (GPC) is an extension of the W3C
|
||||
WebDriver protocol.
|
||||
|
||||
### setGlobalPrivacyControl
|
||||
|
||||
```
|
||||
POST /session/:sessionId/privacy
|
||||
```
|
||||
|
||||
> GPC documentation: [Set Global Privacy Control](https://www.w3.org/TR/gpc/#set-global-privacy-control)
|
||||
|
||||
Sets the value of the do-not-sell-or-share preference for the current session.
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Description | Type |
|
||||
| ----- | -------------------------------------------------------------------- | ------- |
|
||||
| `gpc` | Whether the browser should perform do-not-sell-or-share interactions | boolean |
|
||||
|
||||
#### Response
|
||||
|
||||
`null`
|
||||
|
||||
### getGlobalPrivacyControl
|
||||
|
||||
```
|
||||
GET /session/:sessionId/privacy
|
||||
```
|
||||
|
||||
> GPC documentation: [Get Global Privacy Control](https://www.w3.org/TR/gpc/#get-global-privacy-control)
|
||||
|
||||
Retrieves the value of the do-not-sell-or-share preference for the current session.
|
||||
|
||||
#### Response
|
||||
|
||||
`boolean` - the preference value
|
||||
|
||||
## Permissions Protocol
|
||||
|
||||
The [Permissions protocol](https://www.w3.org/TR/permissions/) is an extension of the W3C WebDriver
|
||||
@@ -524,6 +563,32 @@ Retrieves the available log types that can be used to call the [`getLog`](#getlo
|
||||
|
||||
`string[]` - an array of log types
|
||||
|
||||
## Storage Access Protocol
|
||||
|
||||
The [Storage Access protocol](https://privacycg.github.io/storage-access/) is an extension of the
|
||||
W3C WebDriver protocol.
|
||||
|
||||
### setStorageAccess
|
||||
|
||||
```
|
||||
POST /session/:sessionId/storageaccess
|
||||
```
|
||||
|
||||
> Storage Access documentation: [Set Storage Access](https://privacycg.github.io/storage-access/#set-storage-access-command)
|
||||
|
||||
Sets the storage access policy of the current browsing context.
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Description | Type |
|
||||
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
|
||||
| `blocked` | Whether storage access should be blocked (`true`) or allowed (`false`) | boolean |
|
||||
| `origin` | The origin to which the policy should be applied. Must be either a valid URL, or an asterisk (`*`) if the policy should apply to all origins. | string |
|
||||
|
||||
#### Response
|
||||
|
||||
`null`
|
||||
|
||||
## Web Authentication Protocol
|
||||
|
||||
The [Web Authentication protocol](https://w3c.github.io/webauthn/) (WebAuthn) is an extension of
|
||||
|
||||
@@ -224,7 +224,7 @@ Deletes a file in the storage.
|
||||
#### Response
|
||||
|
||||
`boolean` - `true` upon successful file deletion, or `false` if the file does not exist in
|
||||
the storage
|
||||
the storage, or if the delete request is invalid.
|
||||
|
||||
### listStorageItems
|
||||
|
||||
|
||||
@@ -118,6 +118,12 @@ appium {driver|plugin} install <install-spec>
|
||||
appium driver install git://github.com/appium/appium-xcuitest-driver.git --source=git --package=appium-xcuitest-driver
|
||||
```
|
||||
|
||||
- Install a branch of XCUITest driver repository using a Git URL:
|
||||
|
||||
```
|
||||
appium driver install git://github.com/appium/appium-xcuitest-driver.git#specific-branch --source=git --package=appium-xcuitest-driver
|
||||
```
|
||||
|
||||
## `list`
|
||||
|
||||
Lists all installed extensions, plus all official extensions that are not installed.
|
||||
@@ -135,6 +141,7 @@ appium {driver|plugin} list
|
||||
| `--installed` | Only list all installed extensions | boolean |
|
||||
| `--json` | Return the result in JSON format | boolean |
|
||||
| `--updates` | List all extensions along with information on whether newer versions are available. Only supported for extensions installed via `npm`. | boolean |
|
||||
| `--verbose` | Show additional details for each extension | boolean |
|
||||
|
||||
#### Example
|
||||
|
||||
|
||||
@@ -31,5 +31,6 @@ The executable has four main subcommands: `server`, `driver`, `plugin`, and `set
|
||||
|
||||
</div>
|
||||
|
||||
Appium also recognizes several [environment variables](./env-vars.md), which may be used for
|
||||
advanced configuration.
|
||||
The Appium server also recognizes several [environment variables](./env-vars.md) and
|
||||
[insecure feature names](./insecure-features.md), though drivers and plugins can also define
|
||||
variables and features of their own.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
hide:
|
||||
- toc
|
||||
|
||||
title: Insecure Features
|
||||
---
|
||||
|
||||
The Appium server implements [a security protection mechanism](../../guides/security.md) that
|
||||
allows the management of various insecure features.
|
||||
|
||||
The following features are defined on the server level and can be used even without drivers, but
|
||||
they can only be enabled using the wildcard (`*`) prefix:
|
||||
|
||||
| Feature Name | Description |
|
||||
| ------------------- | ------------------------------------------------------------------------------- |
|
||||
| `session_discovery` | Allows retrieving the list of active server sessions via `GET /appium/sessions` |
|
||||
|
||||
Of course, Appium drivers and plugins are free to define additional insecure features of their own.
|
||||
The following features are defined by official plugins:
|
||||
|
||||
| Feature Name | Plugin | Description |
|
||||
| ----------------------- | ---------------- | ---------------------------------------------------------- |
|
||||
| `execute_driver_script` | `execute_driver` | Allows sending a request that has multiple Appium commands |
|
||||
@@ -48,6 +48,8 @@ appium
|
||||
| `--log-no-colors` | Disable colors in the server log | boolean | `false` |
|
||||
| `--log-timestamp` | Show timestamps in the server log | boolean | `false` |
|
||||
| `--long-stacktrace` | Add long stack traces to log entries. Recommended for debugging only. | boolean | `false` |
|
||||
| `--max-ipc-data-size` | Maximum byte size of IPC message objects. | integer | `1048576` (1MB) |
|
||||
| `--max-ipc-topics` | Maximum number of IPC topics per session. | integer | `1000` |
|
||||
| `--no-perms-check` | Skip various permission checks on the server startup | boolean | `false` |
|
||||
| `--nodeconfig` | JSON configuration for registering Appium as a node with Selenium Grid 3 | object | |
|
||||
| `--plugin` | Plugin-specific configuration. Keys should correspond to plugin package names | object | |
|
||||
|
||||
@@ -5,8 +5,8 @@ hide:
|
||||
title: Reference
|
||||
---
|
||||
|
||||
This section of the Appium documentation provides a reference to the two main interfaces within the
|
||||
Appium server: the command-line executable, and the supported API endpoints.
|
||||
This section of the Appium documentation provides a reference to the core interfaces supported within the
|
||||
Appium server:
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
@@ -16,10 +16,16 @@ Appium server: the command-line executable, and the supported API endpoints.
|
||||
|
||||
Learn how to use the Appium command-line executable
|
||||
|
||||
- :material-lan-connect: [**Session Properties**](./session/index.md)
|
||||
|
||||
---
|
||||
|
||||
See the values of global Appium session properties
|
||||
|
||||
- :material-cloud-braces: [**API Endpoints**](./api/index.md)
|
||||
|
||||
---
|
||||
|
||||
View endpoints supported by the Appium server
|
||||
View endpoints supported by the core Appium server
|
||||
|
||||
</div>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user