Compare commits

..
Author SHA1 Message Date
Jonathan Lipps 8476bd3f65 chore: publish
- appium@2.18.0
 - @appium/base-driver@9.17.0
 - @appium/base-plugin@2.3.6
 - @appium/docutils@1.1.0
 - @appium/driver-test-support@0.7.9
 - @appium/eslint-config-appium-ts@1.0.4
 - @appium/execute-driver-plugin@4.0.5
 - @appium/fake-plugin@3.2.6
 - @appium/images-plugin@3.1.2
 - @appium/logger@1.7.0
 - @appium/opencv@3.0.9
 - @appium/plugin-test-support@0.3.53
 - @appium/storage-plugin@0.1.2
 - @appium/support@6.1.0
 - @appium/test-support@3.1.9
 - @appium/types@0.25.3
 - @appium/universal-xml-plugin@1.0.33
2025-04-25 12:00:24 -07:00
Kazuaki Matsuo c6aa31bda0 docs(appium): address default timeout in newCommandTimeout (#21222) 2025-04-23 23:14:45 -07:00
Edgars Eglītis ffaffc11d9 docs: remove SeleniumConf banner (#21221) 2025-04-23 11:51:00 -07:00
renovate[bot] 8edc4143a8 chore(universal-xml-plugin): update dependency fast-xml-parser to v5.2.1 (#21220)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-23 19:16:38 +03:00
Edgars Eglītis ca9e79b00d docs: update Appium 2 migration guide (#21215)
* docs: rewrite Appium 2 migration guide

* docs: reorder breaking changes

* docs: identify changed endpoints

* docs: improve code example

* docs: address comments
2025-04-22 23:46:12 +03:00
renovate[bot] d870b7aca7 chore(execute-driver-plugin): update dependency webdriverio to v9.12.7 (#21218)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 15:26:48 +00:00
renovate[bot] 6cb9e846cc chore(deps): update eslint-related packages (#21216)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 11:28:39 +00:00
renovate[bot] 5b33298ca7 chore(deps): update eslint-related packages (#21214)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-20 06:41:51 +00:00
renovate[bot] e88ea8c783 chore(docutils): update dependency mkdocs-material to v9.6.12 (#21211)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-18 11:10:51 +00:00
renovate[bot] c9ecc152c9 chore(execute-driver-plugin): update dependency webdriverio to v9.12.6 (#21210)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-17 12:16:18 +00:00
Mykola Mokhnach 97c62676fc chore(base-driver): Mark /session/:sessionId/network_connection deprecated (#21209) 2025-04-16 19:43:57 +02:00
renovate[bot] 9e9cbdeaf1 chore(types): update dependency type-fest to v4.40.0 (#21208)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-16 11:32:56 +00:00
renovate[bot] 2422e44082 chore(deps): update dependency typescript-eslint to v8.30.1 (#21206)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 16:35:00 +00:00
Teodor Nikolov 05a562ca9e docs(appium): add NovaWindows driver to Appium other drivers list (#21202) 2025-04-14 22:39:40 +09:00
Mykola Mokhnach a17291db4e chore(base-driver): Mark IME commands and receive_async_response as deprecated (#21201) 2025-04-14 08:43:48 +02:00
renovate[bot] 1cc2e3324a chore(execute-driver-plugin): update dependency webdriverio to v9.12.5 (#21200)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-12 14:30:49 +00:00
renovate[bot] 1be94b9f7a chore(deps): update dependency @types/node to v22.14.1 (#21199)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-12 10:24:11 +00:00
renovate[bot] bd9ce0c78e chore(deps): update dependency lerna to v8.2.2 (#21197)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-11 14:59:35 +00:00
renovate[bot] 649e997e07 chore(deps): update dependency eslint-config-prettier to v10.1.2 (#21195)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-11 11:08:33 +02:00
renovate[bot] d782d28326 chore(deps): update dependency tsd to v0.32.0 (#21194)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-10 19:44:16 +03:00
renovate[bot] 17f25ecb33 chore(support): update dependency sharp to v0.34.1 (#21191)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-09 17:08:00 +03:00
renovate[bot] eb559dc833 chore(deps): update dependency typescript-eslint to v8.29.1 (#21189)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-08 13:14:10 +00:00
renovate[bot] a765ff99d5 chore(deps): update dependency eslint-import-resolver-typescript to v4.3.2 (#21186)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-07 09:48:23 +02:00
Edgars Eglītis 7979351543 fix(ci): run on all Node LTS versions instead of only active (#21185)
* fix(ci): run on LTS versions instead of only active

* chore: address comments
2025-04-06 20:38:42 +03:00
Edgars Eglītis 55da22fc40 feat(docutils): add MkDocs Material codeblock & text format features (#21184)
* chore(docutils): reorder Markdown extensions alphabetically

* feat(docutils): add MkDocs Material codeblock features

* chore(docutils): explicitly add Markdown tables support

* feat(docutils): add MkDocs Material linked tabs

* feat(docutils): add MkDocs Material text format features

* feat(docutils): add MkDocs Material task list
2025-04-06 19:57:32 +03:00
renovate[bot] d4a0126ad5 chore(support): update dependency sharp to v0.34.0 (#21183)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-06 14:03:53 +03:00
renovate[bot] 846c60a3c7 chore(deps): update eslint-related packages to v9.24.0 (#21182)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-06 10:08:02 +00:00
renovate[bot] 3b054fe8d1 chore(execute-driver-plugin): update dependency webdriverio to v9.12.4 (#21180)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-05 14:04:18 +00:00
renovate[bot] dafc7abaec chore(docutils): update dependency typescript to v5.8.3 (#21179)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-05 09:24:31 +00:00
renovate[bot] f6eb67e838 chore(universal-xml-plugin): update dependency fast-xml-parser to v5.2.0 (#21178)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-04 19:16:16 +03:00
renovate[bot] 1e07b227a1 chore(execute-driver-plugin): update dependency webdriverio to v9.12.3 (#21177)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-04 12:23:33 +02:00
Mykola Mokhnach 1de5d0a0e8 fix(logger): Error stack logging (#21176) 2025-04-04 09:44:31 +02:00
renovate[bot] 25c0600b9f chore(types): update dependency type-fest to v4.39.1 (#21173)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-03 15:25:52 +00:00
renovate[bot] 229f24d2e3 chore(deps): update dependency @types/node to v22.14.0 (#21172)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-03 10:13:13 +00:00
Edgars Eglītis 804b1a3c15 fix(docutils): add & adjust various log messages (#21160)
* fix(docutils): add & adjust various log messages

* fix: use npm from support package for npm calls
2025-04-02 20:36:57 +03:00
renovate[bot] 742ad1e9b5 chore(types): update dependency type-fest to v4.39.0 (#21168)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 14:26:37 +00:00
renovate[bot] 71bfb5ada9 chore(docutils): update dependency mkdocs-material to v9.6.11 (#21167)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 11:01:24 +00:00
renovate[bot] 49d8b242e4 chore(deps): update definitelytyped (#21164)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-01 22:19:17 +00:00
renovate[bot] 2b4b4c2a39 chore(deps): update dependency typescript-eslint to v8.29.0 (#21165)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-01 13:38:23 +00:00
renovate[bot] 228e479785 chore(docutils): update dependency mkdocs-material to v9.6.10 (#21161)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 12:45:12 +00:00
Regan Karlewicz a82476f2fc feat(base-driver): Accept x-request-id as override to generated requestId in handleLogContext (#21154) 2025-03-31 09:22:38 +02:00
renovate[bot] fcc66a1b4c chore(deps): update dependency eslint-import-resolver-typescript to v4.3.1 (#21159)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-30 09:10:24 +02:00
renovate[bot] d7e383c5f4 chore(docutils): update dependency yaml to v2.7.1 (#21158)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-30 09:10:12 +02:00
renovate[bot] 28b091a450 chore(execute-driver-plugin): update dependency webdriverio to v9.12.2 (#21151)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-29 07:00:32 +01:00
renovate[bot] f55de14a4f chore(deps): update dependency eslint-import-resolver-typescript to v4.2.7 (#21155)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-29 07:00:15 +01:00
Mykola Mokhnach d334ad4b4a chore(storage-plugin): Use base driver import for W3C error response creation (#21153) 2025-03-29 06:32:08 +01:00
renovate[bot] 423ef391bb chore(deps): update definitelytyped (#21147)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-27 09:41:50 +01:00
renovate[bot] 283cd2c695 chore(deps): update dependency eslint-import-resolver-typescript to v4.2.5 (#21146)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-27 02:25:26 +00:00
renovate[bot]andMykola Mokhnach 2e08ebbe16 chore(test-support): update dependency sinon to v20 (#21143)
* chore(test-support): update dependency sinon to v20

* remove usingPromise

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Mykola Mokhnach <mokhnach@gmail.com>
2025-03-26 11:56:56 +01:00
renovate[bot] 7713985a50 chore(deps): update eslint-related packages (#21142)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 20:04:51 +00:00
renovate[bot] e508e217ed chore(test-support): update dependency sinon to v19.0.5 (#21141)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 12:49:25 +00:00
renovate[bot] f09640ccf3 chore(deps): update definitelytyped (#21139)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 23:36:34 +00:00
renovate[bot] 8f30a5461e chore(types): update dependency type-fest to v4.38.0 (#21140)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 17:10:50 +00:00
renovate[bot] 6ba28ebc28 chore(deps): update eslint-related packages to v9.23.0 (#21138)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-22 09:15:40 +00:00
Mykola Mokhnach c24d2ac461 feat: Add a possibility to mask sensitive log values depending on request headers (#21123) 2025-03-21 23:12:41 +01:00
renovate[bot] 4e381ada17 chore(deps): update dependency @types/node to v22.13.11 (#21135)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-21 15:55:28 +00:00
renovate[bot] 5b971de540 chore(test-support): update dependency sinon to v19.0.4 (#21130)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 17:35:07 +01:00
renovate[bot] de737bba73 chore(eslint-config-appium-ts): update dependency eslint-import-resolver-typescript to v4 (#21119)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 16:47:50 +01:00
renovate[bot] d8225d0176 chore(deps): update dependency typescript-eslint to v8.27.0 (#21131)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 14:27:09 +01:00
renovate[bot] aaab7b956e chore(execute-driver-plugin): update dependency webdriverio to v9.12.1 (#21129)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 11:22:58 +00:00
renovate[bot] 8d77bd3e06 chore(support): update dependency axios to v1.8.4 (#21127)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 09:22:57 +01:00
renovate[bot] b7dcd3f7b9 chore(deps): update dependency @types/express to v5.0.1 (#21126)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 07:52:40 +00:00
renovate[bot] eccae91099 chore(docutils): update dependency consola to v3.4.2 (#21124)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-18 15:27:48 +00:00
zhangxh075 3425da9cf6 docs: update zh contributing documentation (#21117)
* Translate Validation of Individual Arguments via AJV section

* Complete the translation of the config system file
2025-03-17 22:13:19 +02:00
Jonathan Lipps 603d1e7fb2 chore: publish
- appium@2.17.1
 - @appium/base-driver@9.16.4
 - @appium/base-plugin@2.3.5
 - @appium/docutils@1.0.34
 - @appium/driver-test-support@0.7.8
 - @appium/execute-driver-plugin@4.0.4
 - @appium/fake-plugin@3.2.5
 - @appium/images-plugin@3.1.1
 - @appium/storage-plugin@0.1.1
 - @appium/support@6.0.8
 - @appium/test-support@3.1.8
 - @appium/universal-xml-plugin@1.0.32
2025-03-17 11:24:00 -07:00
Mykola Mokhnach f800c9d760 fix(base-driver): Exclude proxied headers from the server response (#21120) 2025-03-17 19:18:19 +01:00
renovate[bot] 8f5a6c47a9 chore(docutils): update dependency mkdocs-material to v9.6.9 (#21121)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 17:32:59 +00:00
renovate[bot] 157108c70c chore(deps): update dependency eslint-import-resolver-typescript to v3.9.1 (#21115)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-16 14:00:18 +00:00
renovate[bot] 7c5e3ee86e chore(docutils): update dependency mkdocs-git-revision-date-localized-plugin to v1.4.5 (#21112)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-15 09:18:40 +01:00
renovate[bot] 6e836e0860 chore(deps): update dependency eslint-import-resolver-typescript to v3.9.0 (#21113)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-15 09:18:26 +01:00
renovate[bot] 65492d7f3b chore(universal-xml-plugin): update dependency fast-xml-parser to v5 (#21109)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-14 12:38:14 +01:00
renovate[bot] c07045ea48 chore(docutils): update dependency mkdocs-material to v9.6.8 (#21108)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-14 08:35:46 +01:00
renovate[bot] 1f68195ff3 chore(deps): update dependency eslint-import-resolver-typescript to v3.8.7 (#21107)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-14 07:31:45 +00:00
renovate[bot] fd09d7fa0f chore(deps): update dependency eslint-import-resolver-typescript to v3.8.6 (#21103)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-13 09:36:52 +00:00
renovate[bot] 04f140a4ad chore(execute-driver-plugin): update dependency webdriverio to v9.12.0 (#21072) 2025-03-12 19:55:32 +01:00
renovate[bot] 3f077db410 chore(support): update dependency axios to v1.8.3 (#21102)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-12 15:03:59 +00:00
renovate[bot] 3bda97f3c5 chore(deps): update dependency eslint-import-resolver-typescript to v3.8.5 (#21101)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-12 11:26:23 +00:00
Jonathan Lipps 7c05f5c213 chore: publish
- appium@2.17.0
 - @appium/base-driver@9.16.3
 - @appium/base-plugin@2.3.4
 - @appium/docutils@1.0.33
 - @appium/driver-test-support@0.7.7
 - @appium/execute-driver-plugin@4.0.3
 - @appium/fake-driver@5.7.2
 - @appium/fake-plugin@3.2.4
 - @appium/images-plugin@3.1.0
 - @appium/plugin-test-support@0.3.52
 - @appium/storage-plugin@0.1.0
 - @appium/support@6.0.7
 - @appium/test-support@3.1.7
 - @appium/tsconfig@0.3.5
 - @appium/types@0.25.2
 - @appium/universal-xml-plugin@1.0.31
2025-03-11 14:40:58 -07:00
Mykola Mokhnach e68757b349 fix(base-driver): Fix proxy url generation (#21099) 2025-03-11 19:27:57 +01:00
renovate[bot] f007b46a65 chore(deps): update eslint-related packages (#21097)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-11 10:28:26 +00:00
Edgars Eglītis f9b51ec526 docs: add storage-plugin documentation (#21096)
* chore: fix typo

* chore: list storage-plugin as a known plugin

* docs: align storage-plugin docs with other plugins

* chore: address comments
2025-03-10 19:45:28 +02:00
renovate[bot] 884173f967 chore(docutils): update dependency mkdocs-git-revision-date-localized-plugin to v1.4.4 (#21093)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-10 16:37:11 +00:00
Mykola Mokhnach f3b1f3556c chore(storage-plugin): Simplify add to storage logic (#21092) 2025-03-09 20:12:10 +01:00
Sakura Nene ef3d781d88 docs(appium): fix a broken character that caused incorrect rendering of mkdocs (#21090) (#21091) 2025-03-09 17:28:08 +01:00
Mykola Mokhnach 15280b80d2 feat(storage-plugin): Tune the files keeping behaviour (#21086) 2025-03-09 09:34:32 +01:00
renovate[bot] 365a7b1770 chore(deps): update eslint-related packages to v9.22.0 (#21085)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-08 22:49:45 +00:00
Kazuaki Matsuo d1e7124d4d docs(base-driver): remove outdated READMEs (#21083) 2025-03-08 09:18:25 -08:00
renovate[bot] cb799d7ab8 chore(deps): update dependency @types/node to v22.13.10 (#21084)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-08 13:24:36 +00:00
Mykola Mokhnach ba4aa394d1 feat: Add storage plugin (#21075) 2025-03-08 09:21:10 +01:00
Kazuaki Matsuo a4eda0054b chore(fake-driver): accept 3.0.0-beta.0 as well (#21076) 2025-03-07 18:51:49 -08:00
renovate[bot] dbd0d321e0 chore(deps): update dependency eslint-config-prettier to v10.1.1 (#21081)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-07 14:39:41 +00:00
renovate[bot] c6d5383425 chore(support): update dependency axios to v1.8.2 (#21080)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-07 10:40:52 +00:00
Mykola Mokhnach 859f3c430a test(images-plugin): Fix test host (#21079) 2025-03-07 09:03:54 +01:00
Mykola Mokhnach e3560e0bee test: Update tests of images plugin (#21078) 2025-03-07 07:56:28 +01:00
renovate[bot] 51eea37e93 chore(deps): update dependency finalhandler to v2 (#21074)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-06 14:21:47 +01:00
renovate[bot] 053c105f6f chore(types): update dependency type-fest to v4.37.0 (#21073)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-06 14:21:16 +01:00
kkb912002 0c50504266 feat(images-plugin): supports image elements included in actions. (#21055) 2025-03-06 14:20:55 +01:00
renovate[bot] 1766a8d0cf chore(docutils): update dependency mkdocs-git-revision-date-localized-plugin to v1.4.1 (#21071)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-06 11:40:34 +00:00
renovate[bot] dbad59f1ff chore(docutils): update dependency typescript to v5.8.2 (#21057)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-06 06:34:24 +00:00
renovate[bot] b70ddd50a8 chore(deps): update definitelytyped (#21067)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-06 02:11:37 +00:00
renovate[bot] bbe04a7ac0 chore(deps): update dependency typescript-eslint to v8.26.0 (#21068)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-05 22:16:07 +00:00
renovate[bot] a7c9f6198a chore(workflows): update peter-evans/create-pull-request action to v7.0.8 (#21066)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-05 16:30:05 +00:00
renovate[bot] c5723e7655 chore(tsconfig): update dependency @tsconfig/node14 to v14.1.3 (#21065)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-05 10:59:02 +00:00
1125 changed files with 82082 additions and 96606 deletions
-10
View File
@@ -1,10 +0,0 @@
<!-- CODEGRAPH_START -->
## CodeGraph
In repositories indexed by CodeGraph (a `.codegraph/` directory exists at the repo root), reach for it BEFORE grep/find or reading files when you need to understand or locate code:
- **MCP tool** (when available): `codegraph_explore` answers most code questions in one call — the relevant symbols' verbatim source plus the call paths between them, including dynamic-dispatch hops grep can't follow. Name a file or symbol in the query to read its current line-numbered source. If it's listed but deferred, load it by name via tool search.
- **Shell** (always works): `codegraph explore "<symbol names or question>"` prints the same output.
If there is no `.codegraph/` directory, skip CodeGraph entirely — indexing is the user's decision.
<!-- CODEGRAPH_END -->
-17
View File
@@ -1,17 +0,0 @@
{
"permissions": {
"allow": ["mcp__codegraph__*"]
},
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "codegraph prompt-hook"
}
]
}
]
}
}
-5
View File
@@ -1,5 +0,0 @@
# CodeGraph data files — local to each machine, not for committing.
# Ignore everything in .codegraph/ except this file itself, so transient
# files (the database, daemon.pid, sockets, logs) never show up in git.
*
!.gitignore
-9
View File
@@ -1,9 +0,0 @@
{
"mcpServers": {
"codegraph": {
"type": "stdio",
"command": "codegraph",
"args": ["serve", "--mcp", "--path", "."]
}
}
}
+1 -2
View File
@@ -1,14 +1,13 @@
# editorconfig.org
root = true
[*.{js,cjs,mjs,jsx,ts,cts,mts,tsx,json,jsonc}]
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 120
[*.md]
trim_trailing_whitespace = false
+4
View File
@@ -23,10 +23,14 @@ targets:
path: ./packages/appium
- type: npm
path: ./packages/base-driver
- type: npm
path: ./packages/eslint-config-appium-ts
- type: npm
path: ./packages/fake-driver
- type: npm
path: ./packages/support
- type: npm
path: ./packages/test-support
- type: npm
path: ./packages/types
- type: npm
+9 -8
View File
@@ -3,6 +3,7 @@ description: Create a new bug report.
title: '🐞 bug: <title>'
labels: [Bug, Needs Triage]
body:
- type: markdown
attributes:
value: ':stop_sign: _Make sure you are reporting an issue. For general questions, please use [http://discuss.appium.io](http://discuss.appium.io)._'
@@ -12,9 +13,9 @@ body:
label: Is there an existing issue for this?
description: 'Please [search :mag: the issues](https://github.com/appium/appium/issues) to check if this bug has already been reported.'
options:
- label: I have searched the existing issues
required: true
- label: I have searched the existing issues
required: true
- type: input
attributes:
label: Appium Version
@@ -48,7 +49,7 @@ body:
description: |
You can retrieve the latest server/driver/plugin version number by running `npm info <package-name> version`. If you are not up to date, please try to reproduce your issue after updating all affected components.
options:
- label: I confirm the issue is still reproducible with the latest component versions
- label: I confirm the issue is still reproducible with the latest component versions
- type: textarea
attributes:
@@ -81,10 +82,10 @@ body:
:warning: _Remember to redact or remove any sensitive information!_
value: |
- Debug details (`appium --show-debug-info`):
- Last component version(s) which did _not_ exhibit the problem:
- Platform and version of device under test:
- Real device or emulator/simulator:
- Debug details (`appium --show-debug-info`):
- Last component version(s) which did _not_ exhibit the problem:
- Platform and version of device under test:
- Real device or emulator/simulator:
- type: textarea
attributes:
+1 -1
View File
@@ -1,5 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: ❓ Question
- name: ❓ Question
url: https://discuss.appium.io/
about: Please use the Appium forum for any questions.
+2 -1
View File
@@ -1,8 +1,9 @@
name: 💡 Feature Request
description: Suggest an idea for this project.
title: '💡 feat: <title>'
title: "💡 feat: <title>"
labels: [Enhancement]
body:
- type: textarea
attributes:
label: Is your feature request related to a problem?
-77
View File
@@ -1,77 +0,0 @@
name: Setup Node, Install, Build
description: |
Common setup for Appium CI jobs: checkout, setup Node, install deps, optional build, optional V8 cache clear.
inputs:
node-version:
description: Node.js version to setup
required: true
install-command:
description: npm install command
required: false
default: npm ci --foreground-scripts
run-build:
description: Whether to run npm run build
required: false
default: 'true'
runs:
using: composite
steps:
- name: Use Node.js ${{ inputs.node-version }}
uses: actions/setup-node@v7.0.0
with:
node-version: ${{ inputs.node-version }}
cache: npm
- name: SocketDev Security Check
uses: SocketDev/action@v1.3.2
with:
mode: firewall-free
- name: Install dependencies
shell: bash
run: |
# Replace npm with sfw npm in the install command
install_cmd="${{ inputs.install-command }}"
sfw_install_cmd="${install_cmd//npm /sfw npm }"
# Socket Firewall can fail to reach its own backend (a transient
# network error unrelated to the actual npm install) and, in that
# case, either exit non-zero or exit 0 without having actually
# completed the install, leaving node_modules incomplete. We only
# want to fall back to a plain (non-firewalled) install when we can
# positively attribute the failure to *that* Socket Firewall error —
# a real npm/package problem (bad version, checksum mismatch, failing
# postinstall script, etc.) must fail the job as-is, not be silently
# retried and potentially masked.
sfw_log="$(mktemp)"
set +e
$sfw_install_cmd 2>&1 | tee "$sfw_log"
sfw_exit="${PIPESTATUS[0]}"
set -e
sfw_infra_failure=0
if grep -qi 'Socket Firewall encountered an unexpected error' "$sfw_log"; then
sfw_infra_failure=1
fi
install_incomplete=0
if [ "$sfw_exit" -eq 0 ]; then
npm ls --depth=0 >/dev/null 2>&1 || install_incomplete=1
fi
rm -f "$sfw_log"
if [ "$sfw_infra_failure" -eq 1 ] && { [ "$sfw_exit" -ne 0 ] || [ "$install_incomplete" -eq 1 ]; }; then
echo "::warning::Socket Firewall failed to reach its backend; retrying with a plain npm install"
$install_cmd
elif [ "$sfw_exit" -ne 0 ]; then
echo "::error::npm install failed"
exit "$sfw_exit"
elif [ "$install_incomplete" -eq 1 ]; then
echo "::error::npm install appears incomplete and is not attributable to a Socket Firewall failure"
exit 1
fi
- name: Build packages
if: ${{ inputs.run-build == 'true' }}
shell: bash
run: npm run build
-9
View File
@@ -1,9 +0,0 @@
# 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.
+7 -7
View File
@@ -68,10 +68,10 @@ labels:
matcher:
files: ['packages/driver-test-support/**']
- label: '@appium/oxc-config'
- label: '@appium/eslint-config-appium-ts'
sync: true
matcher:
files: ['packages/oxc-config/**']
files: ['packages/eslint-config-appium-ts/**']
- label: '@appium/execute-driver-plugin'
sync: true
@@ -118,11 +118,6 @@ labels:
matcher:
files: ['packages/schema/**']
- label: '@appium/semantic-release-config'
sync: true
matcher:
files: ['packages/semantic-release-config/**']
- label: '@appium/support'
sync: true
matcher:
@@ -133,6 +128,11 @@ labels:
matcher:
files: ['packages/strongbox/**']
- label: '@appium/test-support'
sync: true
matcher:
files: ['packages/test-support/**']
- label: '@appium/tsconfig'
sync: true
matcher:
+1 -1
View File
@@ -13,4 +13,4 @@ jobs:
name: Auto-Label PRs
runs-on: ubuntu-latest
steps:
- uses: fuxingloh/multi-labeler@v5.0.0
- uses: fuxingloh/multi-labeler@v4
+37 -135
View File
@@ -3,11 +3,10 @@ on:
push:
branches:
- master
- appium4
# this list of paths could potentially impact the build
paths:
- '**/tsconfig*.json'
- 'packages/base-driver/test-fixtures/**/*'
- 'packages/base-driver/static/**/*'
- 'packages/*/test/**'
- 'packages/*/bin'
- 'packages/**/*.ts'
@@ -16,18 +15,18 @@ on:
- 'package*.json'
- 'lerna.json'
- '.npmrc'
- '.mocharc.js'
- '.github/workflows/build.yml' # this file
- 'oxlint.config.mjs'
- 'oxfmt.config.mjs'
- '.eslintrc'
- '.eslintignore'
- '!**/sample-code/**'
- '!packages/*/docs/**'
pull_request:
branches:
- master
- appium4
paths:
- '**/tsconfig*.json'
- 'packages/base-driver/test-fixtures/**/*'
- 'packages/base-driver/static/**/*'
- 'packages/*/test/**'
- 'packages/*/bin'
- 'packages/**/*.ts'
@@ -36,9 +35,10 @@ on:
- 'package*.json'
- 'lerna.json'
- '.npmrc'
- '.mocharc.js'
- '.github/workflows/build.yml' # this file
- 'oxlint.config.mjs'
- 'oxfmt.config.mjs'
- '.eslintrc'
- '.eslintignore'
- '!**/sample-code/**'
- '!packages/*/docs/**'
@@ -50,154 +50,56 @@ permissions:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
cancel-in-progress: true
jobs:
prepare_matrix:
uses: appium/appium-workflows/.github/workflows/node-lts-matrix.yml@main
prepare_e2e_packages:
runs-on: ubuntu-latest
outputs:
packages: ${{ steps.discover-packages.outputs.packages }}
versions: ${{ steps.generate-matrix.outputs.lts }}
steps:
- uses: actions/checkout@v7.0.1
- name: Discover packages with e2e tests
id: discover-packages
run: |
packages=()
for package_dir in packages/*/; do
package_json="${package_dir}package.json"
if [[ -f "$package_json" ]]; then
# Check if package.json has test:e2e script and it's not a no-op
has_e2e=$(node -e "
try {
const pkg = require('./$package_json');
const script = pkg.scripts && pkg.scripts['test:e2e'];
if (script && !script.includes('echo') && !script.includes('No e2e tests')) {
console.log('true');
}
} catch(e) {
// Ignore errors
}
")
if [[ "$has_e2e" == "true" ]]; then
# Use the directory path without packages/ prefix (remove trailing slash)
package_name="${package_dir%/}"
package_name="${package_name#packages/}"
packages+=("$package_name")
fi
fi
done
# Convert array to JSON array for GitHub Actions matrix
if [[ ${#packages[@]} -eq 0 ]]; then
echo "No packages with e2e tests found"
packages_json="[]"
else
# Use jq to create a compact single-line JSON array
packages_json=$(printf '%s\n' "${packages[@]}" | jq -R '.' | jq -s '.' | jq -c '.')
fi
echo "packages=$packages_json" >> $GITHUB_OUTPUT
echo "Found packages with e2e tests:"
echo "$packages_json" | jq -r '.[]' | sed 's/^/ - /'
- name: Select all current LTS versions of Node.js
id: generate-matrix
uses: msimerson/node-lts-versions@v1
test-smoke:
test:
needs:
- prepare_matrix
name: Smoke Tests
- prepare_matrix
name: Tests
strategy:
matrix:
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
runs-on: ubuntu-latest
os:
- ubuntu-latest
# TODO: Windows is not stable and slow to run
# - windows-latest
# TODO: Enable below envs after all tests have been verified green
# - macos-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7.0.1
- name: Setup, install and build
uses: ./.github/actions/setup-build
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
install-command: npm ci --foreground-scripts
run-build: 'true'
- name: Run smoke tests
run: npm run test:smoke
test-unit:
needs:
- prepare_matrix
name: Unit Tests
strategy:
matrix:
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
- name: Setup, install and build
uses: ./.github/actions/setup-build
cache: 'npm'
- name: Install dependencies
uses: bahmutov/npm-install@v1
with:
node-version: ${{ matrix.node-version }}
useRollingCache: true
install-command: npm ci --foreground-scripts
run-build: 'true'
- name: Run unit tests
run: npm run test:unit
test-types:
needs:
- prepare_matrix
name: Type Tests
strategy:
matrix:
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
- name: Setup, install and build
uses: ./.github/actions/setup-build
with:
node-version: ${{ matrix.node-version }}
install-command: npm ci --foreground-scripts
run-build: 'true'
- name: Run type tests
run: npm run test:types
test-e2e:
needs:
- prepare_matrix
- prepare_e2e_packages
name: E2E Tests - ${{ matrix.package_dir }} (Node ${{ matrix.node-version }})
if: ${{ github.event_name == 'pull_request' }}
strategy:
fail-fast: false
matrix:
node-version: ${{ fromJSON(needs.prepare_matrix.outputs.versions) }}
package_dir: ${{ fromJSON(needs.prepare_e2e_packages.outputs.packages) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
- name: Setup, install and build
uses: ./.github/actions/setup-build
with:
node-version: ${{ matrix.node-version }}
install-command: npm ci --foreground-scripts
run-build: 'true'
- name: Run E2E tests for ${{ matrix.package_dir }}
run: |
set -o pipefail
cd "packages/${{ matrix.package_dir }}"
npm run test:e2e
- name: Run smoke, unit & E2E tests
run: npm run test:ci
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
- name: Setup and install (no build)
uses: ./.github/actions/setup-build
- uses: actions/checkout@v4
- name: Install dependencies
uses: bahmutov/npm-install@v1
with:
node-version: lts/*
useRollingCache: true
install-command: npm ci
run-build: 'false'
- name: Lint
- name: ESLint
run: npm run lint:ci
- name: Format check
run: npm run format:check
- name: Verify changelog generation
run: npm run verify:changelog-generation
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v7.0.1
uses: actions/checkout@v4
- name: Cleanup
run: |
-44
View File
@@ -1,44 +0,0 @@
# Collects translation statistics from Crowdin for the last calendar month
# and posts them to Slack grouped by project, language, and translator
name: Crowdin Translation Statistics
on:
workflow_dispatch:
schedule:
# Run on the first day of each month at 9:00 AM UTC
- cron: 0 9 1 * *
jobs:
collect-stats:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- project_id_var: CROWDIN_DOCS_PROJECT_ID
project_name: appium-documentation
- project_id_var: CROWDIN_INSPECTOR_PROJECT_ID
project_name: appium-inspector
steps:
- uses: actions/checkout@v7.0.1
- name: Use Node.js LTS
uses: actions/setup-node@v7.0.0
with:
node-version: lts/*
cache: 'npm'
- name: Install Dependencies
run: npm ci
- name: Collect Crowdin Stats for ${{ matrix.project_name }}
id: crowdin-stats
run: node ./scripts/crowdin-stats.mjs > crowdin-stats-${{ matrix.project_name }}.json
env:
CROWDIN_PROJECT_ID: ${{ vars[matrix.project_id_var] }}
CROWDIN_TOKEN: ${{ secrets.CROWDIN_DOCS_TOKEN }}
- name: Post to Slack for ${{ matrix.project_name }}
uses: slackapi/slack-github-action@v4.0.0
with:
errors: true
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload-file-path: crowdin-stats-${{ matrix.project_name }}.json
@@ -4,19 +4,19 @@ name: Sync Crowdin Docs Translations
on:
workflow_dispatch:
schedule:
- cron: 0 0 * * *
# TODO: Uncomment the scheduler as soon as we have existing translations
# imported to Crowdin
# schedule:
# - cron: 0 0 * * 0
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Use Node.js LTS
uses: actions/setup-node@v7.0.0
uses: actions/setup-node@v4
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@v8.1.1
uses: peter-evans/create-pull-request@v7.0.8
with:
token: ${{ github.token }}
commit-message: 'docs(appium): Update documentation translations'
@@ -15,9 +15,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
- uses: actions/checkout@v4
- name: Use Node.js LTS
uses: actions/setup-node@v7.0.0
uses: actions/setup-node@v4
with:
node-version: lts/*
cache: 'npm'
+9 -3
View File
@@ -10,11 +10,17 @@ permissions:
jobs:
prepare_matrix:
uses: appium/appium-workflows/.github/workflows/node-lts-matrix.yml@main
runs-on: ubuntu-latest
outputs:
versions: ${{ steps.generate-matrix.outputs.lts }}
steps:
- name: Select all current LTS versions of Node.js
id: generate-matrix
uses: msimerson/node-lts-versions@v1
check:
needs:
- prepare_matrix
- prepare_matrix
name: Check
runs-on: ${{ matrix.os }}
strategy:
@@ -23,7 +29,7 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v7.0.0
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Install Appium
+2 -2
View File
@@ -37,9 +37,9 @@ jobs:
name: Docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
- uses: actions/checkout@v4
- name: Install dependencies (Node.js)
uses: bahmutov/npm-install@v1.12.1
uses: bahmutov/npm-install@v1
with:
useRollingCache: true
install-command: npm ci
+2 -2
View File
@@ -13,11 +13,11 @@ jobs:
env:
FOSSA_API_KEY: ${{secrets.FOSSA_API_KEY}}
steps:
- uses: actions/checkout@v7.0.1
- uses: actions/checkout@v4
with:
ref: master
- name: Install dependencies
uses: bahmutov/npm-install@v1.12.1
uses: bahmutov/npm-install@v1
- name: Install fossa-cli
run: |
curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install-latest.sh | bash
@@ -1,37 +0,0 @@
# Collects GitHub contribution statistics from the Appium organization for the last calendar month
# and posts it to Slack
name: GitHub Contribution Statistics
on:
workflow_dispatch:
schedule:
# Run on the first day of each month at 09:00 AM UTC
- cron: 0 9 1 * *
jobs:
collect-contrib-stats:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
- name: Use Node.js LTS
uses: actions/setup-node@v7.0.0
with:
node-version: lts/*
cache: 'npm'
- name: Install Dependencies
run: npm ci
- name: Collect GitHub Contribution Stats
id: github-stats
run: node ./scripts/github-contrib-stats.mjs > github-contrib-stats.json
env:
# GITHUB_TOKEN is optional - if not provided, uses unauthenticated requests (rate limited)
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Post to Slack
uses: slackapi/slack-github-action@v4.0.0
with:
errors: true
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
webhook-type: incoming-webhook
payload-file-path: github-contrib-stats.json
-228
View File
@@ -1,228 +0,0 @@
name: Appium Server Release
on:
workflow_dispatch:
inputs:
dry_run:
description: 'Dry run (no publishing or tagging)'
required: true
type: boolean
default: true
recover_missing_only:
description: 'Recovery mode: skip version bump, publish only packages missing on npm at their current package.json version'
required: true
type: boolean
default: false
allow_legacy_peer_deps:
description: 'Beta branch only: pass --legacy-peer-deps to lerna''s internal npm calls, for when a dependent''s peerDependencies range still lags a just-bumped major (causes ERESOLVE otherwise). Leave off unless you hit that failure.'
required: true
type: boolean
default: false
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
jobs:
release:
runs-on: ubuntu-latest
# keep this branch name in sync with env.BETA_BRANCH below - the `env` context isn't available
# to jobs.<job_id>.if (GitHub Actions resolves it before job-level env is set up)
if: (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/appium4') && contains(fromJSON('["mykola-mokhnach", "jlipps", "eglitise", "KazuCocoa"]'), github.actor)
env:
BETA_BRANCH: appium4
steps:
- name: Checkout repository
uses: actions/checkout@v7.0.1
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 }}
RECOVER_MISSING_ONLY: ${{ inputs.recover_missing_only }}
ALLOW_LEGACY_PEER_DEPS: ${{ inputs.allow_legacy_peer_deps }}
run: |
set -euo pipefail
# On the beta branch ($BETA_BRANCH), every release is a beta prerelease anchored at its
# target major (see packages/semantic-release-config's "Next-major beta branches" docs
# for the equivalent semantic-release behavior this mirrors).
#
# allow_legacy_peer_deps: independent next-major beta.0 bumps can briefly outrun a
# dependent's committed peerDependencies range, aborting lerna's internal lockfile
# refresh with ERESOLVE. Opt-in only - it masks a real (if temporary) peer mismatch.
LEGACY_PEER_DEPS_FLAGS=""
if [ "$ALLOW_LEGACY_PEER_DEPS" = "true" ]; then
LEGACY_PEER_DEPS_FLAGS="--npm-client-args=--legacy-peer-deps"
fi
BETA_FLAGS=""
DIST_TAG_FLAGS=""
if [ "${{ github.ref_name }}" = "$BETA_BRANCH" ]; then
BETA_FLAGS="--conventional-prerelease --preid beta $LEGACY_PEER_DEPS_FLAGS"
DIST_TAG_FLAGS="--dist-tag beta"
fi
# Prints "<pkg_name>@<pkg_version>" to stdout for each non-private workspace package
# whose current package.json version is not yet on npm.
find_missing_packages() {
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" >&2
continue
fi
pkg_spec="${pkg_name}@${pkg_version}"
if ! npm view "$pkg_spec" version >/dev/null 2>&1; then
echo "$pkg_spec"
fi
done
}
# Resolves the workspace directory of a package given its npm name.
package_dir_for() {
local target="$1"
for pkg_json in packages/*/package.json; do
if [ ! -f "$pkg_json" ]; then
continue
fi
if [ "$(jq -r '.name // empty' "$pkg_json")" = "$target" ]; then
dirname "$pkg_json"
return 0
fi
done
return 1
}
# Publishes each "<pkg_name>@<pkg_version>" package spec passed as an argument.
# `lerna publish` has no per-package scope filter, so this runs `npm publish`
# directly from each package's directory instead. Returns non-zero if any
# individual publish failed; npm publish's own exit code is taken as authoritative,
# no npm registry re-scan is done to double-check it.
publish_missing_packages() {
echo "Publishing missing packages one-by-one"
local overall_status=0
for pkg_spec in "$@"; do
pkg_name="${pkg_spec%@*}"
pkg_dir="$(package_dir_for "$pkg_name")"
if [ -z "$pkg_dir" ]; then
echo "Could not resolve workspace directory for ${pkg_name}"
overall_status=1
continue
fi
echo "Publishing ${pkg_spec}"
set +e
(cd "$pkg_dir" && npm publish $DIST_TAG_FLAGS)
publish_exit_code=$?
set -e
if [ $publish_exit_code -ne 0 ]; then
echo "npm publish failed for ${pkg_spec} (exit code ${publish_exit_code})"
overall_status=1
fi
done
return $overall_status
}
if [ "$RECOVER_MISSING_ONLY" = "true" ]; then
echo "Recovery mode: scanning for packages missing on npm at their current package.json version"
mapfile -t missing < <(find_missing_packages)
if [ ${#missing[@]} -eq 0 ]; then
echo "No missing packages found; nothing to do"
exit 0
fi
echo "Missing package versions on npm:"
printf ' - %s\n' "${missing[@]}"
if [ "$DRY_RUN" = "true" ]; then
echo "Dry run: not publishing"
exit 0
fi
if ! publish_missing_packages "${missing[@]}"; then
echo "Recovery incomplete: one or more packages failed to publish"
exit 1
fi
echo "All missing packages published successfully"
exit 0
fi
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 $BETA_FLAGS
else
echo "Running lerna publish for real"
set +e
release_output="$(npm run release -- --yes $BETA_FLAGS $DIST_TAG_FLAGS 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"
mapfile -t missing < <(find_missing_packages)
if [ ${#missing[@]} -gt 0 ]; then
echo "Missing package versions on npm before scoped recovery:"
printf ' - %s\n' "${missing[@]}"
if ! publish_missing_packages "${missing[@]}"; then
echo "Recovery incomplete: one or more packages failed to publish"
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
-50
View File
@@ -1,50 +0,0 @@
# This job only publishes new releases on GitHub and updates the changelog, without publishing to NPM.
# It can be used if the standard release workflow failed and *only* published to NPM.
name: Appium Server Version (Without NPM Publish)
on:
workflow_dispatch:
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
jobs:
version:
runs-on: ubuntu-latest
# keep this branch name in sync with env.BETA_BRANCH below - the `env` context isn't available
# to jobs.<job_id>.if (GitHub Actions resolves it before job-level env is set up)
if: (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/appium4') && contains(fromJSON('["mykola-mokhnach", "jlipps", "eglitise", "KazuCocoa"]'), github.actor)
env:
BETA_BRANCH: appium4
steps:
- name: Checkout repository
uses: actions/checkout@v7.0.1
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: |
BETA_FLAGS=""
if [ "${{ github.ref_name }}" = "$BETA_BRANCH" ]; then
BETA_FLAGS="--conventional-prerelease --preid beta"
fi
npx lerna version --exact --yes $BETA_FLAGS
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check for "On Hold" label
uses: egmacke/action-check-label@v5
uses: egmacke/action-check-label@v3
with:
label: On Hold
state: absent
+9 -4
View File
@@ -4,7 +4,12 @@ on:
types: [opened, edited, synchronize, reopened]
jobs:
lint:
uses: appium/appium-workflows/.github/workflows/pr-title.yml@main
with:
config-preset: angular
conventional:
name: PR Title
runs-on: ubuntu-latest
steps:
- uses: beemojs/conventional-pr-action@v3
with:
config-preset: angular
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+28 -22
View File
@@ -1,32 +1,38 @@
# 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:
push:
# Runs when any new Appium tag is pushed = there is a new release
# Does not trigger for tags with a slash, e.g. 1.0/beta
tags:
- appium@*
- '!appium@*beta*'
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@v7.0.1
with:
fetch-depth: 0 # ensure the docs branch is also fetched
- 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: Publish docs
run: npm run docs:publish
- uses: actions/checkout@v4
- run: |
git config user.name github-actions
git config user.email github-actions@github.com
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
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
+2 -2
View File
@@ -23,8 +23,8 @@ jobs:
name: Check Renovate Configs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
- uses: actions/checkout@v4
- name: Validate Renovate Config
uses: rinchsan/renovate-config-validator@v0.2.1
uses: rinchsan/renovate-config-validator@v0.2.0
with:
pattern: '{.renovaterc.json,renovate/default.json}'
+10
View File
@@ -0,0 +1,10 @@
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
View File
@@ -1,9 +0,0 @@
{
"mcpServers": {
"codegraph": {
"type": "stdio",
"command": "codegraph",
"args": ["serve", "--mcp"]
}
}
}
+11
View File
@@ -0,0 +1,11 @@
// @ts-check
'use strict';
module.exports = {
require: ['ts-node/register'],
// forbids use of .only() in CI
forbidOnly: Boolean(process.env.CI),
color: true,
timeout: '5s',
};
+13
View File
@@ -0,0 +1,13 @@
**/node_modules/**
**/build/**
**/fixtures/**
**/*.min.*
**/*.md
package-lock.json
package.json
**/.vscode/**
**/*.html
**/generated/**
# generated
packages/types/lib/appium-config.ts
**/*.hbs
+4 -1
View File
@@ -1,6 +1,9 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["github>appium/appium//renovate/default"],
"schedule": ["after 10pm", "before 5:00am"],
"schedule": [
"after 10pm",
"before 5:00am"
],
"timezone": "America/Vancouver"
}
+3 -5
View File
@@ -5,7 +5,7 @@ most of which have their own changelogs. Links to these individual changelogs ar
## Main Appium Module
* ### [Appium Changelog](packages/appium/CHANGELOG.md)
* ### [Appium 2 Changelog](packages/appium/CHANGELOG.md)
* [Appium 1.x Changelog](https://github.com/appium/appium/blob/1.x/CHANGELOG.md)
## Drivers / Clients
@@ -16,7 +16,6 @@ to driver/client documentation
* [execute-driver-plugin](packages/execute-driver-plugin/CHANGELOG.md)
* [images-plugin](packages/images-plugin/CHANGELOG.md)
* [relaxed-caps-plugin](packages/relaxed-caps-plugin/CHANGELOG.md)
* [storage-plugin](packages/storage-plugin/CHANGELOG.md)
* [universal-xml-plugin](packages/universal-xml-plugin/CHANGELOG.md)
## Other Modules
@@ -29,12 +28,12 @@ to driver/client documentation
* [fake-plugin](packages/fake-plugin/CHANGELOG.md)
* [logger](packages/logger/CHANGELOG.md)
* [opencv](packages/opencv/CHANGELOG.md)
* [oxc-config](packages/oxc-config/CHANGELOG.md)
* [plugin-test-support](packages/plugin-test-support/CHANGELOG.md)
* [schema](packages/schema/CHANGELOG.md)
* [semantic-release-config](packages/semantic-release-config/CHANGELOG.md)
* [storage-plugin](packages/storage-plugin/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)
@@ -43,5 +42,4 @@ 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
View File
@@ -0,0 +1,48 @@
## Code of Conduct
### What is this code of conduct for?
Appium is a piece of technology, but **the core of the Appium community is the people in it**. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, gender identity and expression, sexual orientation, ability, physical appearance, body size, race, age, socioeconomic status, religion (or lack thereof), or other marginalized aspect of comunity members. We expect all members of the Appium community to abide by this Code of Conduct whenever interacting in Appium venues (pull requests, GitHub issues, 1-1 or group chat, meetups, conferences, etc...)
### Examples of inappropriate behavior
Because we come from a variety of backgrounds, we don't want to assume that everyone has the same assumptions about what is and isn't appropriate. Here are some examples of inappropriate behavior that are incompatible with our community's ethos:
* Spamming, trolling, intentionally disrupting conversations, or irrelevant solicitation or advertisement
* Making demeaning or discriminatory comments
* Making negative assumptions about someone's background, abilities, or intentions
* Harassing or stalking individuals (online or in person)
* Giving someone unwelcome sexual attention or making unwelcome physical contact (in the case of an IRL event)
* Sharing sexual images or using sexually explicit language
In general: treat others how you would like to be treated, were you in their place. Don't be a jerk. _Do_ ask questions. _Do_ keep conflicts productively focused on technical issues. _Do_ think before you speak; remember that what is perceived as a funny witticism in your group of friends might be hurtful or reinforce hurtful stereotypes in the context of our diverse online community. _Do_ remember that we are all people, not robots, and all equally deserving of sensitivity and respect. (If and when robots join our community, let's treat them with respect too!)
### What will organizers do about inappropriate behavior?
If we notice you doing or saying something inappropriate, an organizer will explain why it's inappropriate and ask you to stop. We won't demonize or vilify you. But please do stop the inappropriate behavior so we can get back to writing and discussing code in a safe environment. If you have philosophical disagreements about what's actually inappropriate, please take them to a separate public or private conversation with an Appium maintainer so we don't turn pull requests into an ethics debate.
If you keep doing unacceptable things, we'll likely ban you, report you to GitHub, or take other appropriate action.
### What if I see or am subject to what feels like inappropriate behavior?
Let us know! Please notify a community organizer as soon as possible. Full contact information is listed in the [Contact Info](#contact-info) section of this document. All communications will be kept strictly confidential, unless otherwise required by law. No issue will be considered too inconsequential or unimportant for us to have a conversation about.
### Contact Info
If you need to report an incident, please contact any of the following organizers directly:
* Isaac Murchie [email](mailto:isaac@saucelabs.com) [twitter](https://twitter.com/imurchie)
* Jonathan Lipps [email](mailto:jlipps@saucelabs.com) [twitter](https://twitter.com/jlipps)
### Credit, License, and Attribution
This Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/).
It's inspired among other things by:
* [Citizen Code of Conduct](http://citizencodeofconduct.org/)
* [npmjs](https://www.npmjs.com/policies/conduct)
* [Geek Feminism](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy)
* [Ashe Dryden](http://www.ashedryden.com/blog/codes-of-conduct-101-faq)
* [Model View Culture](https://modelviewculture.com/issues/events)
* [Open Source & Feelings](http://osfeels.com/conduct).
-4
View File
@@ -50,22 +50,18 @@ 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.
+16
View File
@@ -0,0 +1,16 @@
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.
+13 -17
View File
@@ -1,3 +1,5 @@
[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://vshymanskyy.github.io/StandWithUkraine/)
<p align="center">
<a href="https://appium.io/">
<img alt="Appium" src="https://raw.githubusercontent.com/appium/appium/master/packages/appium/docs/overrides/assets/images/appium-logo-horiz.png" width="500">
@@ -13,7 +15,6 @@
[![Monthly Downloads](https://img.shields.io/npm/dm/appium.svg)](https://npmjs.org/package/appium)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fappium%2Fappium.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fappium%2Fappium?ref=badge_shield)
[![StandWithUkraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://github.com/vshymanskyy/StandWithUkraine/)
[![CeasefireInGaza](https://img.shields.io/badge/Ceasefire_Now-%F0%9F%87%B5%F0%9F%87%B8-red?style=flat)](https://www.unrwa.org/)
</div>
@@ -38,13 +39,18 @@ programming languages, which means there is an entire ecosystem of related softw
* [__Clients__](#clients) allow writing Appium tests in your programming language of choice
* [__Plugins__](#plugins) allow to further extend Appium functionality
## Upgrading From Older Versions
## Migrating From Appium 1 to Appium 2
The Appium team only provides support for the most recent version of Appium. If you wish to upgrade from
an older major Appium version, please refer to the migration guides:
As of January 1st, 2022, the Appium team no longer maintains or supports Appium 1. All officially
supported platform drivers are only compatible with Appium 2.
* [Appium v2 to v3](https://appium.io/docs/en/latest/guides/migrating-2-to-3/)
* [Appium v1 to v2](https://appium.io/docs/en/latest/guides/migrating-1-to-2/)
__[Please read the Migration Guide](https://appium.io/docs/en/latest/guides/migrating-1-to-2/) if you
are still using Appium 1.__
> [!WARNING]
> If you use Appium Desktop or Appium Server GUI, you will not be able to upgrade to Appium 2, as
both of these tools have been deprecated. Please use [Appium Inspector](https://github.com/appium/appium-inspector)
in combination with a standalone Appium 2 server.
## Installation
@@ -133,7 +139,7 @@ appium plugin uninstall <plugin-name>
## Server Command Line Interface
In order to start sending commands to the Appium server, it must be running on the URL and port
where your client library expects it to listen. [Appium's command-line interface](http://appium.io/docs/en/latest/cli/server/)
where your client library expects it to listen. [Appium's command-line interface](http://appium.io/docs/en/latest/cli/args/)
is used to launch and configure the server:
```bash
@@ -198,16 +204,6 @@ contribution of project development and leadership!
</a>
</p>
<p align="center">
<a href="https://www.testmuai.com">
<picture>
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-dark.png" media="(prefers-color-scheme: dark)"/>
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-light.png" media="(prefers-color-scheme: light)"/>
<img src="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-dark.png" width="300" alt="TestMu AI (formerly LambdaTest)"/>
</picture>
</a>
</p>
### Other Sponsors
A full list of sponsors is available at our [Sponsors page](https://appium.io/docs/en/latest/sponsors/).
+1 -1
View File
@@ -3,4 +3,4 @@
The old Appium 1.x docs used to be in this directory. Now, they are available only on the [1.x
branch](https://github.com/appium/appium/tree/1.x/docs).
Current Appium docs are located in [packages/appium/docs](../packages/appium/docs) in this repo.
Appium 2.x docs are located in [packages/appium/docs](../packages/appium/docs) in this repo.
+20 -27
View File
@@ -4,32 +4,25 @@ This documentation is a note for the opencollective payout.
<img width="200" alt="Screenshot 2024-09-17 at 11 04 32 PM" src="https://github.com/user-attachments/assets/5d598a46-8aa3-41e0-aadc-ce3f34b10f6b">
2. Select `Appium` in `Who is paying`
3. Select `Invite someone` and fill in a user name to pay payouts for
4. Select `Invoice` for `Select the type of expense`
5. Check the `I have read and understood the instructions and conditions` agreement
6. Select `No, generate an invoice for me`
- Keep blank for the `Additional invoice information (optional)`
8. Fill in the description in the `Item Description`, date and amount for `Expense Items`
- for TCs:
- `<year-month> contribution as a TC https://github.com/appium/appium/blob/master/GOVERNANCE.md#the-technical-committee and maintaining Appium project itself (development, review etc)`
- i.e. `2024-07 contribution as a TC https://github.com/appium/appium/blob/master/GOVERNANCE.md#the-technical-committee and maintaining Appium project itself (development, review etc)`
- for individuals
- `PR contribution: <PRs>` for PRs. `Community contribution in Q&A forum at https://discuss.appium.io/` for appium forums
- E.g.
- `PR contribution: https://github.com/appium/dotnet-client/pull/810, https://github.com/appium/dotnet-client/pull/808`
- `PR contribution: https://github.com/appium/java-client/pull/2206, https://github.com/appium/java-client/pull/2203 and a few PRs`
- `Community contribution in Q&A forum at https://discuss.appium.io/`
- Translations
- e.g.
- `Translation contributions for https://crowdin.com/project/appium-documentation`
- For Date
- today
- For Amount
- Put the payment amount in USD
9. Fill in title in `Title` in `Additional details`
2. Select `Invoice`
3. Type proper account name in `Who is being paid for this expense?`
- The form depends on the target user
4. Select `Next`
5. Input expense info and complete the form. Then, the user will recieve the expense info.
- Expense title: `<year-month> contribution payout`
- e.g. `2024-07 contribution payout`
10. Submit expense
11. Update the expense url in our payout sheet
12. Approve each expense after getting a response for each expense
- Description in "Set invoice details"
- for TCs:
- `<year-month> contribution as a TC https://github.com/appium/appium/blob/master/GOVERNANCE.md#the-technical-committee and maintaining Appium project itself (development, review etc)`
- i.e. `2024-07 contribution as a TC https://github.com/appium/appium/blob/master/GOVERNANCE.md#the-technical-committee and maintaining Appium project itself (development, review etc)`
- for individuals
- `PR contribution: <PRs>` for PRs. `Community contribution in Q&A forum at https://discuss.appium.io/` for appium forums
- E.g.
- `PR contribution: https://github.com/appium/dotnet-client/pull/810, https://github.com/appium/dotnet-client/pull/808`
- `PR contribution: https://github.com/appium/java-client/pull/2206, https://github.com/appium/java-client/pull/2203 and a few PRs`
- `Community contribution in Q&A forum at https://discuss.appium.io/`
- Amount
- Type the amount in `USD`
6. Approve each expense after getting response for each expense
<img width="500" alt="Screenshot 2024-09-11 at 8 40 35 PM" src="https://github.com/user-attachments/assets/462cda69-1ce7-458c-b319-dda87cf10d65">
+24
View File
@@ -0,0 +1,24 @@
import tsConfig from '@appium/eslint-config-appium-ts';
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/**',
],
},
];
+1 -2
View File
@@ -14,8 +14,7 @@
"version": {
"conventionalCommits": true,
"createRelease": "github",
"allowBranch": ["master", "appium4"],
"exact": true
"allowBranch": "master"
}
},
"ignoreChanges": ["**/test/**", "**/*.md"],
-11
View File
@@ -1,11 +0,0 @@
import appiumConfig, {defineConfig, ignorePatterns as appiumIgnorePatterns} from '@appium/oxc-config/oxfmt';
export default defineConfig({
...appiumConfig,
ignorePatterns: [
...appiumIgnorePatterns,
'packages/appium/docs/**',
'packages/schema/lib/appium-config.schema.json',
'packages/types/lib/appium-config.ts',
],
});
-11
View File
@@ -1,11 +0,0 @@
import appiumConfig, {defineConfig, ignorePatterns as appiumIgnorePatterns} from '@appium/oxc-config/oxlint';
export default defineConfig({
extends: [appiumConfig],
ignorePatterns: [
...appiumIgnorePatterns,
'packages/appium/docs/**/assets/**',
'packages/appium/docs/**/js/**',
'packages/appium/sample-code/**',
],
});
+24192 -11260
View File
File diff suppressed because it is too large Load Diff
+93 -54
View File
@@ -4,31 +4,28 @@
"private": true,
"description": "Automation for Apps.",
"keywords": [
"android",
"automation",
"firefoxos",
"ios",
"javascript",
"selenium",
"testing",
"webdriver"
"webdriver",
"ios",
"android",
"firefoxos",
"testing"
],
"homepage": "https://appium.io",
"bugs": {
"url": "https://github.com/appium/appium/issues"
},
"license": "Apache-2.0",
"author": "https://github.com/appium",
"repository": {
"type": "git",
"url": "https://github.com/appium/appium.git"
},
"license": "Apache-2.0",
"author": "https://github.com/appium",
"workspaces": [
"packages/*"
],
"publishConfig": {
"access": "public"
},
"scripts": {
"build": "run-s build:*",
"build:compile": "tsc -b",
@@ -50,11 +47,9 @@
"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": "oxfmt -c oxfmt.config.mjs .",
"format:check": "oxfmt -c oxfmt.config.mjs --check .",
"lint": "oxlint -c oxlint.config.mjs .",
"lint:ci": "oxlint -c oxlint.config.mjs --quiet .",
"lint:fix": "oxlint -c oxlint.config.mjs --fix .",
"lint": "eslint .",
"lint:ci": "eslint --quiet .",
"lint:fix": "run-s \"lint -- --fix\"",
"prepare": "run-p rebuild",
"prepublishOnly": "run-s rebuild",
"preversion": "run-s rebuild",
@@ -62,77 +57,121 @@
"rebuild": "run-s clean build",
"reinstall": "run-s clean clean:deps ci",
"reinstall:angry": "npm run clean:dangerously && npm ci",
"release": "lerna publish --exact",
"release": "lerna publish",
"stage-synced-pkgs": "git add -A packages/appium/README.md \"packages/*/package.json\"",
"start": "appium",
"sync-pkgs": "node ./scripts/sync-monorepo-packages.mjs",
"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,engines",
"sync-pkgs:common-fields:logger": "sync-monorepo-packages --packages=\"packages/logger\" --fields=author,bugs,homepage,engines",
"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",
"test": "run-s test:quick",
"test:ci": "run-s test:smoke test:unit test:types test:e2e",
"test:e2e": "lerna run test:e2e",
"test:quick": "run-s lint test:unit test:types",
"test:slow": "run-s test:quick test:smoke test:e2e",
"test:smoke": "lerna run test:smoke",
"test:smoke": "smoker --all test:smoke",
"test:types": "lerna run test:types",
"test:unit": "lerna run test",
"upload": "gulp github-upload",
"verify:changelog-generation": "node ./scripts/verify-changelog-generation.mjs",
"zip": "zip -qr ./appium.zip ./packages/appium",
"zip-and-upload": "run-s zip upload"
},
"prettier": {
"bracketSpacing": false,
"printWidth": 100,
"singleQuote": true
},
"devDependencies": {
"@appium/oxc-config": "1.0.0",
"@tsconfig/node22": "22.0.0",
"@colors/colors": "1.6.0",
"@eslint/js": "9.25.1",
"@tsconfig/node14": "14.1.3",
"@types/argparse": "2.0.17",
"@types/archiver": "6.0.3",
"@types/async-lock": "1.4.2",
"@types/content-disposition": "0.5.9",
"@types/express": "5.0.6",
"@types/finalhandler": "1.2.4",
"@types/base64-stream": "1.0.5",
"@types/bluebird": "3.5.42",
"@types/chai": "5.2.1",
"@types/chai-as-promised": "8.0.2",
"@types/diff": "7.0.2",
"@types/express": "5.0.1",
"@types/jsftp": "2.1.5",
"@types/json-schema": "7.0.15",
"@types/klaw": "3.0.7",
"@types/klaw": "3.0.6",
"@types/lockfile": "1.0.4",
"@types/lodash": "4.17.16",
"@types/method-override": "3.0.0",
"@types/mime-types": "3.0.1",
"@types/morgan": "1.9.10",
"@types/node": "24.13.3",
"@types/picomatch": "4.0.3",
"@types/mocha": "10.0.10",
"@types/mv": "2.1.4",
"@types/ncp": "2.0.8",
"@types/node": "22.14.1",
"@types/pluralize": "0.0.33",
"@types/semver": "7.8.0",
"@types/semver": "7.7.0",
"@types/serve-favicon": "2.5.7",
"@types/shell-quote": "1.7.5",
"@types/sinon": "22.0.0",
"@types/sinon": "17.0.4",
"@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/uuid": "10.0.0",
"@types/which": "3.0.4",
"@types/wrap-ansi": "3.0.0",
"@types/ws": "8.18.1",
"@types/yargs": "17.0.35",
"asyncbox": "6.4.2",
"conventional-changelog-conventionalcommits": "9.3.1",
"cpy-cli": "7.0.0",
"cross-env": "10.1.0",
"finalhandler": "2.1.1",
"@types/xmldom": "0.1.34",
"@types/yargs": "17.0.33",
"asyncbox": "3.0.0",
"chai": "5.2.0",
"chai-as-promised": "8.0.1",
"conventional-changelog-conventionalcommits": "7.0.2",
"cpy-cli": "5.0.0",
"cross-env": "7.0.3",
"eslint": "9.25.1",
"eslint-config-prettier": "10.1.2",
"eslint-import-resolver-typescript": "4.3.4",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-mocha": "10.5.0",
"eslint-plugin-promise": "7.2.1",
"finalhandler": "2.1.0",
"get-port": "5.1.1",
"json-schema-to-typescript": "15.0.4",
"lerna": "10.0.1",
"lerna": "8.2.2",
"log-symbols": "4.1.0",
"midnight-smoker": "8.0.0",
"mjpeg-consumer": "2.0.0",
"mjpeg-server": "0.3.1",
"npm-run-all2": "9.0.3",
"rimraf": "6.1.3",
"serve-static": "2.2.1",
"sinon": "22.1.0",
"teen_process": "4.2.1",
"tsd": "0.33.0",
"typescript": "6.0.3",
"webdriverio": "9.31.2",
"ws": "8.21.3"
"mocha": "11.1.0",
"npm-run-all2": "6.2.6",
"prettier": "3.5.3",
"rewiremock": "3.14.5",
"rimraf": "5.0.10",
"serve-static": "1.16.2",
"sinon": "20.0.0",
"sync-monorepo-packages": "1.0.2",
"ts-node": "10.9.2",
"tsd": "0.32.0",
"typescript": "5.8.3",
"typescript-eslint": "8.31.0",
"validate.js": "0.13.1",
"webdriverio": "9.12.7",
"ws": "8.18.1",
"yaml-js": "0.3.1"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
"npm": ">=8"
},
"publishConfig": {
"access": "public"
},
"overrides": {
"@sidvind/better-ajv-errors": {
"ajv": "8.20.0"
"ajv": "8.17.1"
},
"ajv-formats": {
"ajv": "8.20.0"
"ajv": "8.17.1"
},
"http-cache-semantics": "4.2.0"
},
"engines": {
"node": "^22.22.2 || ^24.15.0 || >=26.0.0",
"npm": ">=10"
"http-cache-semantics": "4.1.1"
}
}
-343
View File
@@ -3,349 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [4.0.0-beta.1](https://github.com/appium/appium/compare/appium@4.0.0-beta.0...appium@4.0.0-beta.1) (2026-09-19)
### Bug Fixes
* **deps:** catch up peerDependencies to published beta.0; drop bootstrap_packages ([#22793](https://github.com/appium/appium/issues/22793)) ([b09efc3](https://github.com/appium/appium/commit/b09efc31c6967bbcf2c4314db9d2a0b6454fa8fb))
## [4.0.0-beta.0](https://github.com/appium/appium/compare/appium@3.7.0...appium@4.0.0-beta.0) (2026-09-19)
### ⚠ BREAKING CHANGES
* **base-driver:** align timeouts endpoints closer to W3C standard (#22776)
* users relying on the implicit debug default for console/file logs will now see info-level output unless they explicitly pass --log-level debug.
* **support:** Any script or tool that consumes Appium CLI output (driver/plugin list/install/update, doctor, etc.) and relies on the previous stream layout will need to be updated. Previously, non-JSON human-readable output (info/success/warning messages) was written to STDERR, with STDOUT reserved almost exclusively for --json output. Now that output goes to STDOUT, and only actual errors go to STDERR.
* **support:** Scripts that discarded STDOUT (1&gt;/dev/null) to suppress &quot;chatter&quot; while relying on STDERR for status text will now see that text on STDOUT instead.
* **support:** Scripts that captured STDERR to detect/log informational or success messages will no longer see them there — only genuine errors will appear on STDERR. --json output and error behavior are unaffected: --json continues to write clean JSON to STDOUT only, and errors continue to go to STDERR.
* **support:** @appium/logger&#x27;s Log class changes its default output stream from STDERR to STDOUT for all levels except error, and adds an errorStream/stderrLevel pair of properties. Any code that set .stream on a Log instance expecting it to capture all levels (including error) will now need to also set .errorStream to the same target.
* **base-driver:** @appium/base-driver&#x27;s default export (BaseDriver) and @appium/base-driver&#x27;s basedriver/helpers.js default export are removed; use the named exports instead. The appium/driver.js and driver.d.ts re-exports of the default are removed accordingly.
* **base-driver:** BaseDriver.reset() is removed; it was unused, not part of any protocol route or the Driver interface, and had no callers in this monorepo or any driver package that was checked.
* **base-driver:** BaseDriver&#x27;s constructor is removed in favor of inherited DriverCore construction; opts is no longer a required constructor argument (it now defaults to {}, matching DriverCore).
* **support:** @appium/support&#x27;s fs.glob option shape changed from the glob package&#x27;s GlobOptions to a smaller, @appium/support-owned GlobOptions interface. Supported fields: cwd, withFileTypes, absolute, lazy. Options like nodir/ignore/nocase are no longer supported directly — callers needing directory filtering can pass withFileTypes: true and filter on .isFile()/.isDirectory(); callers needing path exclusion can filter the returned array by pattern.
* **appium:** The --allow-cors CLI flag and allow-cors config file property have been removed. Use --allow-insecure&#x3D;*:cors (or --relaxed-security, optionally overridden with --deny-insecure&#x3D;*:cors) instead.
* **base-driver:** ISessionHandler.createSession (@appium/types) and LegacyCreateSessionArgs — overload and type deleted, single-argument signature only.
* **base-driver:** BaseDriver.createSession and AppiumDriver.createSession — collapsed to the single-argument mplementation; capability validation now checks the one argument directly instead of scanning three positions for the first W3C-shaped value.
* **base-driver:** FakeDriver.createSession (and the base-driver e2e test double) — overrides updated to match.
* **base-driver:** RelaxedCapsPlugin.createSession — this plugin existed specifically to normalize capabilities across the (now-gone) three positions; its hook is simplified to a single caps argument.
* **base-driver:** POST /session wire route (w3c.ts) — payloadParams.optional no longer sends capabilities three times into the command args.
* **base-driver:** BaseDriver.getSession, ISessionHandler.getSession, and the GET /session/:sessionId JSONWP route are gone. Use getAppiumSessionCapabilities to retrieve session capabilities and EventCommands.getLogEvents to retrieve event history instead.
* **base-driver:** The appium:eventTimings capability is removed; it only ever controlled whether getSession&#x27;s response was decorated with event history, which getLogEvents already exposes unconditionally.
* **support:** move npm-related helpers into appium package (#22721)
* **logger:** @appium/logger and @appium/support no longer export a default log — import the named log export instead.
* **logger:** AppiumLogger#errorAndThrow has been removed; use errorWithException instead.
* **logger:** Logger#enableProgress, disableProgress, progressEnabled, enableUnicode, disableUnicode have been removed; they were already permanently disabled no-ops.
* **base-plugin:** Plugin#logger has been removed; use Plugin#log instead.
* **base-plugin:** @appium/base-plugin no longer exports BasePlugin as the default export; use the named BasePlugin export.
* Core.driverData, DriverData, and the driverData parameter on ISessionHandler.createSession/deleteSession are gone. Any driver overriding get driverData() or relying on the umbrella driver passing sibling-session data into createSession/deleteSession needs to migrate off this mechanism.
* FakeDriver no longer supports the uniqueApp capability.
* **support:** npm.installPackage now takes a hasAppiumDependency boolean computed by the caller instead of importing the check itself, avoiding a support -&gt; appium dependency.
* **support:** The env export is removed from @appium/support.
* the minimum supported Node.js engine is set to ^22.22.2 || ^24.15.0 || &gt;&#x3D;26.0.0
* **base-driver:** @appium/base-driver no longer exports statusCodes or getSummaryByCode (the jsonwp-status module was removed).
* **base-driver:** errorFromMJSONWPStatusCode (aliased as errorFromCode) has been removed; use errorFromW3CJsonCode for W3C error-signature mapping.
* **base-driver:** ProtocolError instances no longer have a jsonwpCode property.
* **base-driver:** WebDriverProxy (formerly JWProxy) no longer proxies to or interprets responses from downstream servers speaking the legacy MJSONWP protocol; the ProtocolConverter class, COMMAND_URLS_CONFLICTS, and the downstreamProtocol getter/setter have been removed. Downstream automation servers must speak W3C WebDriver.
* **base-driver:** Responses no longer duplicate element references under the legacy ELEMENT key; only the W3C element-6066-11e4-a52e-4f735466cecf key is present. The MJSONWP_ELEMENT_KEY constant has been removed.
* **base-driver:** determineProtocol has been removed, and drivers can no longer produce the legacy {sessionId, status, value} response shape; all responses are now W3C-shaped regardless of how the client formatted its createSession capabilities.
* **base-driver:** DriverCore#setProtocolMJSONWP() has been removed.
* **base-driver:** The deprecated JWProxy export has been removed; use WebDriverProxy instead. Its source also moved from lib/jsonwp-proxy/proxy.js to lib/wd-proxy/proxy.js.
* **base-driver:** DriverCore#isMjsonwpProtocol() has been removed.
* **support:** The following @appium/support exports have been removed: process (getProcessIds, killProcess), mkdirp, imageUtil (requireSharp, cropBase64Image), mjpeg (MJpegStream), net&#x27;s FTP upload
support (FtpUploadOptions, NotHttpUploadOptions; uploadFile only supports http/https now), util&#x27;s uuidV1/uuidV3/uuidV5/localIp/cancellableDelay/multiResolve, and fs&#x27;s readPackageJsonFrom/findRoot/ F_OK/R_OK/W_OK/X_OK.
* **appium:** The --nodeconfig server argument and the server.nodeconfig config file property no longer exist. Users who need to register with a Selenium Grid should use the Grid 4 relay feature instead (see the Grid guide).
* **base-driver:** TLS-enabled Appium servers no longer negotiate SPDY/HTTP2 (spdy/2, spdy/3, spdy/3.1, h2) via ALPN; connections are now served as plain HTTPS (HTTP/1.1) using Node&#x27;s native https module. Clients relying on SPDY or HTTP/2 multiplexing against Appium&#x27;s TLS listener must switch to HTTP/1.1.
* **appium:** &#x60;npm install -g appium --drivers&#x3D;... --plugins&#x3D;...&#x60; no longer installs extensions automatically. Use &#x60;appium driver/plugin install&#x60; or add extensions to package.json instead.
* require(&#x27;@appium/support&#x27;) no longer works; consumers must import it instead.
* require(&#x27;@appium/base-driver&#x27;) no longer works; drivers extending BaseDriver via require must switch to import.
* require(&#x27;@appium/base-plugin&#x27;) no longer works; plugins extending BasePlugin via require must switch to import.
* require(&#x27;appium&#x27;) no longer works; plugins extending the package via require must switch to import.
* require(&#x27;@appium/fake-plugin&#x27;) no longer works; consumers must import it instead.
* require(&#x27;@appium/fake-driver&#x27;) no longer works; consumers must import it instead.
* require(&#x27;@appium/types&#x27;) no longer works; consumers must import it instead.
* require(&#x27;@appium/logger&#x27;) no longer works; consumers must import it instead.
* require(&#x27;@appium/schema&#x27;) no longer works; consumers must import it instead.
### Features
* **appium:** add --app-url-rules server arg to restrict remote app URLs ([#22753](https://github.com/appium/appium/issues/22753)) ([0b104f6](https://github.com/appium/appium/commit/0b104f6bf9b7180b111df40fd6a15b26d649eabd))
* **appium:** remove postinstall autoinstall-extensions script ([#22675](https://github.com/appium/appium/issues/22675)) ([cd0d8f1](https://github.com/appium/appium/commit/cd0d8f14e9d5906ecd1b438038a7f67f74f742fc))
* **appium:** remove Selenium Grid 3 support ([#22677](https://github.com/appium/appium/issues/22677)) ([8fcdcb3](https://github.com/appium/appium/commit/8fcdcb30b07c1ee582256fbef3538d6a3ceea5f2))
* **appium:** replace --allow-cors flag with --allow-insecure&#x3D;*:cors ([#22731](https://github.com/appium/appium/issues/22731)) ([926a0a5](https://github.com/appium/appium/commit/926a0a594935a6cf2e7375eb174eeb15af964f12))
* **appium:** validate extension manifests and extensions.yaml via ajv ([#22732](https://github.com/appium/appium/issues/22732)) ([8840f9f](https://github.com/appium/appium/commit/8840f9f9322b63bc8940c390b8230f1e5306fa62))
* backport diff from master ([#22749](https://github.com/appium/appium/issues/22749)) ([6323df1](https://github.com/appium/appium/commit/6323df1d7354f85cc631508f5cb6a3e35270d4bd))
* **base-driver:** add definitions for all WebDriver BiDi commands ([#22770](https://github.com/appium/appium/issues/22770)) ([ac01aa8](https://github.com/appium/appium/commit/ac01aa83ad73982eea48f856dfc0249b4a26e395))
* **base-driver:** align timeouts endpoints closer to W3C standard ([#22776](https://github.com/appium/appium/issues/22776)) ([93115d1](https://github.com/appium/appium/commit/93115d195773b011306ffb2e6d7d6cc935df0148))
* **base-driver:** remove legacy (M)JSONWP protocol support ([#22681](https://github.com/appium/appium/issues/22681)) ([0b83e77](https://github.com/appium/appium/commit/0b83e77e7a1c24a885d9895a99db30281cf4acea))
* **base-driver:** replace spdy with native https transport ([#22676](https://github.com/appium/appium/issues/22676)) ([ec7de47](https://github.com/appium/appium/commit/ec7de4768fdd8dde9d28db6fc2dfd63be45fd4c6))
* bump minimum supported Node.js engine to ^22.22.2 || ^24.15.0 || &gt;&#x3D;26.0.0 ([#22685](https://github.com/appium/appium/issues/22685)) ([9f4a11e](https://github.com/appium/appium/commit/9f4a11e7190290986d01743557e90e6e44f87638))
* Change the default log level to &#x60;info&#x60; ([#22756](https://github.com/appium/appium/issues/22756)) ([5e644a3](https://github.com/appium/appium/commit/5e644a392fbf11e2ca985408853d7f51aa85be17))
* convert remaining monorepo packages to ESM-only ([#22674](https://github.com/appium/appium/issues/22674)) ([3516e50](https://github.com/appium/appium/commit/3516e50ce6d022f4c0dc539071c593bf2983325f))
* **support:** move env/APPIUM_HOME resolution into appium package ([#22708](https://github.com/appium/appium/issues/22708)) ([8db8e57](https://github.com/appium/appium/commit/8db8e5748e26a7150cacbea09ba3ec52c5ce3fc0))
* **support:** remove deprecated APIs ([#22678](https://github.com/appium/appium/issues/22678)) ([e8ee716](https://github.com/appium/appium/commit/e8ee71685b4c21116e61c88fd8d2f0e39fac2edb))
* **types:** check execute method params against the command signature ([#22754](https://github.com/appium/appium/issues/22754)) ([b25fc20](https://github.com/appium/appium/commit/b25fc20c51a191c33695c1c71fbf129de834b52d))
### Bug Fixes
* address code review cleanups (plist, env memoize, test reuse) ([#22740](https://github.com/appium/appium/issues/22740)) ([0df8834](https://github.com/appium/appium/commit/0df883463812d57d44a0d6d80e9b88f124361934))
* Address several TODOs ([#22762](https://github.com/appium/appium/issues/22762)) ([d6ef7e3](https://github.com/appium/appium/commit/d6ef7e3f1240f161df622c850aea06637f9d1078))
* adjust deprecated JSONWP/MJSONWP routes ([#22763](https://github.com/appium/appium/issues/22763)) ([b129cbb](https://github.com/appium/appium/commit/b129cbbcd55656ae7f33b80b4b52719eb5179509))
* **appium:** lock the extension manifest while driver/plugin commands run ([#22767](https://github.com/appium/appium/issues/22767)) ([a73644f](https://github.com/appium/appium/commit/a73644fb4f4e7b0363117ac1262d7018094b42ff))
* **base-driver:** clean up aborted session creation ([#22733](https://github.com/appium/appium/issues/22733)) ([33d866e](https://github.com/appium/appium/commit/33d866e57506e1546aa4870dde75f7209be107bc))
* declare dependencies that were only resolving via hoisting ([#22758](https://github.com/appium/appium/issues/22758)) ([bcf1c57](https://github.com/appium/appium/commit/bcf1c579997b8dbb8292b1a77583aeef40b11ba4))
* **support:** route non-error CLI console output to stdout ([#22742](https://github.com/appium/appium/issues/22742)) ([4eb4d7f](https://github.com/appium/appium/commit/4eb4d7f317a685d681b6cf4e25c15b617a8cc7df))
### Code Refactoring
* **base-driver:** remove deprecated getSession command ([#22725](https://github.com/appium/appium/issues/22725)) ([f71d980](https://github.com/appium/appium/commit/f71d980779d23e9a19d33285646fad128eae4917))
* **base-driver:** remove deprecated multi-argument createSession overload ([#22730](https://github.com/appium/appium/issues/22730)) ([db72249](https://github.com/appium/appium/commit/db722498739ae7fe1deef1b98e02d04b455a4f70))
* **base-driver:** replace command mixin with explicit named exports ([#22741](https://github.com/appium/appium/issues/22741)) ([506bfee](https://github.com/appium/appium/commit/506bfeeb9aa15c0dd1f481868d347cb9b0d37f86))
* **base-plugin:** remove deprecated legacy logger and default export ([#22718](https://github.com/appium/appium/issues/22718)) ([62db5f0](https://github.com/appium/appium/commit/62db5f0b20c496b495ce27d490453861ddefb259))
* **logger:** remove default exports and dead logging APIs ([#22719](https://github.com/appium/appium/issues/22719)) ([fe24f52](https://github.com/appium/appium/commit/fe24f527a4412ed86c7b5e5afe0c6e26dc569e6b))
* remove deprecated driverData mechanism ([#22716](https://github.com/appium/appium/issues/22716)) ([ef8a8e1](https://github.com/appium/appium/commit/ef8a8e1934bfdc9699c2b9a7eca3e2201b4b9f93))
* **support:** move npm-related helpers into appium package ([#22721](https://github.com/appium/appium/issues/22721)) ([d82d496](https://github.com/appium/appium/commit/d82d496f9e80d6628abface3b623601a6f9791f9))
* **support:** replace glob package with native node:fs glob ([#22735](https://github.com/appium/appium/issues/22735)) ([add1615](https://github.com/appium/appium/commit/add161560701ac7fb2bc372ddefd9317146fbae8))
## [3.7.0](https://github.com/appium/appium/compare/appium@3.6.0...appium@3.7.0) (2026-08-24)
### Features
* **base-driver:** add httpServer.frontRouter for global extension middleware ([#22632](https://github.com/appium/appium/issues/22632)) ([f06226b](https://github.com/appium/appium/commit/f06226b7bb2fb7ee2f3a61833f4a1d7777d4ef21))
* **storage-plugin:** Add route aliases ([#22558](https://github.com/appium/appium/issues/22558)) ([a551c38](https://github.com/appium/appium/commit/a551c3817156bbc7e06793227643a2d11c0c0259))
### Bug Fixes
* **appium:** load @appium/docutils dynamically in docs build script ([#22584](https://github.com/appium/appium/issues/22584)) ([2c0f3fd](https://github.com/appium/appium/commit/2c0f3fd9e319c3bc774bdd2a65148da11094c87c))
* **appium:** parse --webhook as a URI instead of host:port ([#22635](https://github.com/appium/appium/issues/22635)) ([c35a12a](https://github.com/appium/appium/commit/c35a12a51d30fe311ef96ebe386cd9c5540e3927))
* **support:** do not treat a sibling folder as a subpath of the root ([#22586](https://github.com/appium/appium/issues/22586)) ([3a80498](https://github.com/appium/appium/commit/3a8049887dc673a6658c3821a2882e0145c3aa86))
## [3.6.0](https://github.com/appium/appium/compare/appium@3.5.2...appium@3.6.0) (2026-07-25)
### Features
* **appium:** add --allow-unknown-args to tolerate unrecognized server CLI arguments ([#22477](https://github.com/appium/appium/issues/22477)) ([f943fab](https://github.com/appium/appium/commit/f943fab1411826212cfb174e3847e610c25f37b7))
### Bug Fixes
* **appium:** Duplicated module import ([#22519](https://github.com/appium/appium/issues/22519)) ([154ea18](https://github.com/appium/appium/commit/154ea1825281335569f0d6952db527135c75e153))
* typescript config ([#22540](https://github.com/appium/appium/issues/22540)) ([ea6a2e1](https://github.com/appium/appium/commit/ea6a2e117f56c1d7ff459378700494407c51608e))
* Typescript references ([#22458](https://github.com/appium/appium/issues/22458)) ([fd70da7](https://github.com/appium/appium/commit/fd70da7ab407bf1f6fec8a3576b9a33f0aef9b69))
## [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
## [3.1.1](https://github.com/appium/appium/compare/appium@3.1.0...appium@3.1.1) (2025-11-12)
### Bug Fixes
* **appium:** Inject symlinks for all installed extensions ([#21664](https://github.com/appium/appium/issues/21664)) ([8f5aac3](https://github.com/appium/appium/commit/8f5aac3722c9572d61f7e6bef20fe43bb14e0674))
## [3.1.0](https://github.com/appium/appium/compare/appium@3.0.2...appium@3.1.0) (2025-10-08)
### Features
* add 21 WebDriver extension endpoints ([#21577](https://github.com/appium/appium/issues/21577)) ([7f906fc](https://github.com/appium/appium/commit/7f906fcf9a0dd84f348b0b3a79da818281f21835))
* add inspector to plugins installed via `appium setup` ([#21578](https://github.com/appium/appium/issues/21578)) ([1753dcd](https://github.com/appium/appium/commit/1753dcd5e9f4ee3a9bd869f2e846a8a1c68b6970))
* add W3C printPage endpoint ([#21576](https://github.com/appium/appium/issues/21576)) ([cbea4f2](https://github.com/appium/appium/commit/cbea4f2e97d2d291bd67fd98359b37caab1b21fa))
### Bug Fixes
* **appium:** fix base path handling in bidi ([#21611](https://github.com/appium/appium/issues/21611)) ([dad0757](https://github.com/appium/appium/commit/dad07575c9d754751160a53e0fb8053bbddac75b))
## [3.0.2](https://github.com/appium/appium/compare/appium@3.0.1...appium@3.0.2) (2025-09-09)
### Bug Fixes
* **appium:** Return a non-zero exit code if an extension script execution fails ([#21563](https://github.com/appium/appium/issues/21563)) ([5d73a4f](https://github.com/appium/appium/commit/5d73a4fb49a39bd4b81f51763e62f4e52b650f06))
## [3.0.1](https://github.com/appium/appium/compare/appium@3.0.0...appium@3.0.1) (2025-08-20)
**Note:** Version bump only for package appium
## [3.0.0](https://github.com/appium/appium/compare/appium@3.0.0-rc.2...appium@3.0.0) (2025-08-18)
### Appium 3 Is Here! 🚀
[See the blog post](https://appium.io/docs/en/latest/blog/2025/08/07/-appium-3/)
and [the migration guide](https://appium.io/docs/en/latest/guides/migrating-2-to-3/) for more details.
## [3.0.0-rc.2](https://github.com/appium/appium/compare/appium@2.16.2...appium@3.0.0-rc.2) (2025-08-14)
### ⚠ BREAKING CHANGES
* set minimum Node.js version to v20.19.0 (#21394)
### Features
* **appium:** add inspector in preset plugin ([#21114](https://github.com/appium/appium/issues/21114)) ([fdb5c7f](https://github.com/appium/appium/commit/fdb5c7fc4a4ec4078195f879d6c1e2e0e3397419))
* **base-driver:** Make extension name prefix mandatory ([#21110](https://github.com/appium/appium/issues/21110)) ([9402291](https://github.com/appium/appium/commit/9402291f1c634bcb376ff69aef7a7b4d0628cbd4))
* **base-driver:** Migrate errors to typescript ([#21157](https://github.com/appium/appium/issues/21157)) ([d904726](https://github.com/appium/appium/commit/d904726d56353365612c6e0a7dfdb209cc34132b))
* **base-driver:** Remove dependency to validate.js ([#21175](https://github.com/appium/appium/issues/21175)) ([661c5d0](https://github.com/appium/appium/commit/661c5d0bd31f65690fe61c0e396833251c5bae84))
* **base-driver:** Remove deprecated routes ([#21134](https://github.com/appium/appium/issues/21134)) ([4716f40](https://github.com/appium/appium/commit/4716f40226da0a1743f4e570a99c67ce9d581b50))
### Bug Fixes
* **appium:** Add appium module symlink while installing extensions ([#21389](https://github.com/appium/appium/issues/21389)) ([1859ea1](https://github.com/appium/appium/commit/1859ea1c3efc37a3537f55bbfe06d6532b02d7e9))
* use v3 syntax for winston ([#21363](https://github.com/appium/appium/issues/21363)) ([2c94133](https://github.com/appium/appium/commit/2c94133390d04f6160044a1c8bbb31f7925fced8))
### Miscellaneous Chores
* set minimum Node.js version to v20.19.0 ([#21394](https://github.com/appium/appium/issues/21394)) ([37e22c4](https://github.com/appium/appium/commit/37e22c4f9c9920cea3f340841ab1b7c60e3147e9))
## [2.19.0](https://github.com/appium/appium/compare/appium@2.18.0...appium@2.19.0) (2025-06-01)
### Features
* **appium:** implement GET /appium/sessions and deprecate GET /sessions ([#21233](https://github.com/appium/appium/issues/21233)) ([5f6bdfc](https://github.com/appium/appium/commit/5f6bdfc5dfbddab1782a4a86b450c9654ddbd65f))
## [2.18.0](https://github.com/appium/appium/compare/appium@2.17.1...appium@2.18.0) (2025-04-25)
+13 -17
View File
@@ -1,3 +1,5 @@
[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner2-direct.svg)](https://vshymanskyy.github.io/StandWithUkraine/)
<p align="center">
<a href="https://appium.io/">
<img alt="Appium" src="https://raw.githubusercontent.com/appium/appium/master/packages/appium/docs/overrides/assets/images/appium-logo-horiz.png" width="500">
@@ -13,7 +15,6 @@
[![Monthly Downloads](https://img.shields.io/npm/dm/appium.svg)](https://npmjs.org/package/appium)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fappium%2Fappium.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fappium%2Fappium?ref=badge_shield)
[![StandWithUkraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://github.com/vshymanskyy/StandWithUkraine/)
[![CeasefireInGaza](https://img.shields.io/badge/Ceasefire_Now-%F0%9F%87%B5%F0%9F%87%B8-red?style=flat)](https://www.unrwa.org/)
</div>
@@ -38,13 +39,18 @@ programming languages, which means there is an entire ecosystem of related softw
* [__Clients__](#clients) allow writing Appium tests in your programming language of choice
* [__Plugins__](#plugins) allow to further extend Appium functionality
## Upgrading From Older Versions
## Migrating From Appium 1 to Appium 2
The Appium team only provides support for the most recent version of Appium. If you wish to upgrade from
an older major Appium version, please refer to the migration guides:
As of January 1st, 2022, the Appium team no longer maintains or supports Appium 1. All officially
supported platform drivers are only compatible with Appium 2.
* [Appium v2 to v3](https://appium.io/docs/en/latest/guides/migrating-2-to-3/)
* [Appium v1 to v2](https://appium.io/docs/en/latest/guides/migrating-1-to-2/)
__[Please read the Migration Guide](https://appium.io/docs/en/latest/guides/migrating-1-to-2/) if you
are still using Appium 1.__
> [!WARNING]
> If you use Appium Desktop or Appium Server GUI, you will not be able to upgrade to Appium 2, as
both of these tools have been deprecated. Please use [Appium Inspector](https://github.com/appium/appium-inspector)
in combination with a standalone Appium 2 server.
## Installation
@@ -133,7 +139,7 @@ appium plugin uninstall <plugin-name>
## Server Command Line Interface
In order to start sending commands to the Appium server, it must be running on the URL and port
where your client library expects it to listen. [Appium's command-line interface](http://appium.io/docs/en/latest/cli/server/)
where your client library expects it to listen. [Appium's command-line interface](http://appium.io/docs/en/latest/cli/args/)
is used to launch and configure the server:
```bash
@@ -198,16 +204,6 @@ contribution of project development and leadership!
</a>
</p>
<p align="center">
<a href="https://www.testmuai.com">
<picture>
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-dark.png" media="(prefers-color-scheme: dark)"/>
<source srcset="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-light.png" media="(prefers-color-scheme: light)"/>
<img src="packages/appium/docs/overrides/assets/images/sponsor-logo-testmuai-dark.png" width="300" alt="TestMu AI (formerly LambdaTest)"/>
</picture>
</a>
</p>
### Other Sponsors
A full list of sponsors is available at our [Sponsors page](https://appium.io/docs/en/latest/sponsors/).
+7 -23
View File
@@ -3,9 +3,7 @@ site_name: Appium Documentation
repo_url: https://github.com/appium/appium
repo_name: appium/appium
edit_uri: edit/master/packages/appium/docs
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&trade; or registered&reg; 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>
copyright: Copyright &copy; 2012 OpenJS Foundation - <a href="#__consent">Change cookie settings</a>
theme:
logo: assets/images/appium-logo-white.png
@@ -16,33 +14,19 @@ plugins:
blog:
enabled: true
post_excerpt: required
mike:
canonical_version: 'latest'
redirects:
redirect_maps:
'intro/requirements.md': 'quickstart/requirements.md'
'ecosystem/build-drivers.md': 'developing/build-drivers.md'
'ecosystem/build-plugins.md': 'developing/build-plugins.md'
'ecosystem/build-docs.md': 'developing/build-docs.md'
'reference/commands/base-driver.md': 'reference/api/index.md'
'reference/commands/execute-driver-plugin.md': 'reference/api/plugins.md#execute-driver-plugin'
'reference/commands/images-plugin.md': 'reference/api/plugins.md#images-plugin'
'reference/commands/relaxed-caps-plugin.md': 'reference/api/plugins.md#relaxed-caps-plugin'
'reference/commands/universal-xml-plugin.md': 'reference/api/plugins.md#universal-xml-plugin'
'commands/index.md': 'reference/api/index.md'
'commands/base-driver.md': 'reference/api/index.md'
'commands/execute-driver-plugin.md': 'reference/api/plugins.md#execute-driver-plugin'
'commands/images-plugin.md': 'reference/api/plugins.md#images-plugin'
'commands/relaxed-caps-plugin.md': 'reference/api/plugins.md#relaxed-caps-plugin'
'commands/storage-plugin.md': 'reference/api/plugins.md#storage-plugin'
'commands/universal-xml-plugin.md': 'reference/api/plugins.md#universal-xml-plugin'
'cli/index.md': 'reference/cli/index.md'
'cli/args.md': 'reference/cli/server.md'
'cli/env-vars.md': 'reference/cli/env-vars.md'
'cli/extensions.md': 'reference/cli/extensions.md'
'cli/setup.md': 'reference/cli/setup.md'
'reference/commands/base-driver.md': 'commands/base-driver.md'
'reference/commands/execute-driver-plugin.md': 'commands/execute-driver-plugin.md'
'reference/commands/images-plugin.md': 'commands/images-plugin.md'
'reference/commands/relaxed-caps-plugin.md': 'commands/relaxed-caps-plugin.md'
'reference/commands/universal-xml-plugin.md': 'commands/universal-xml-plugin.md'
'contributing/config-system.md': 'developing/config-system.md'
'contributing/develop.md': 'contributing/index.md'
'contributing/develop.md': 'contributing.md'
extra_css:
- assets/stylesheets/extra.css
@@ -17,8 +17,3 @@ authors:
avatar: 'https://avatars.githubusercontent.com/u/4045041?v=4'
slug: 'sai'
url: 'https://saikrishna.tech'
mykola:
name: 'Mykola Mokhnach'
description: 'Appium Core Maintainer'
avatar: https://avatars.githubusercontent.com/u/7767781?v=4
slug: 'mykola'
@@ -1,42 +0,0 @@
---
authors:
- sai
- srini
date: 2025-11-25
---
# Announcing LambdaTest as Appium's Newest Development Partner
As part of our ongoing effort to recognize organizations that meaningfully support the Appium project through dedicated maintainer time, we are excited to welcome our newest Development Partner: LambdaTest!
<!-- more -->
LambdaTest has long been an active participant in the automated testing ecosystem. Today, they are officially formalizing their commitment by investing people—dedicated engineers who will directly support Appium's development, maintenance, and ecosystem growth.
This kind of hands-on contribution is crucial for ensuring Appium continues to evolve. We deeply value partners who empower their engineering teams to contribute code directly to open source rather than just sponsorship.
<div style="text-align:center;width:100%">
<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="300" />
<img src="/docs/en/latest/assets/images/sponsor-logo-lambdatest-light.png#only-light" width="300" />
</a>
</div>
LambdaTest engineers are already contributing actively across several key Appium repositories. Their current focus includes:
* [`appium-mcp`](https://github.com/appium/appium-mcp) – Supporting Appium's implementation of the Model Context Protocol (MCP) to drive forward modern AI-assisted capabilities.
* [`appium-ios-remotexpc`](https://github.com/appium/appium-ios-remotexpc) – Contributing to the native macOS/XPC-based remote execution layer, essential for iOS automation.
* [`appium-ios-tuntap`](https://github.com/appium/appium-ios-tuntap) – Assisting in the development and maintenance of network virtualization and tunneling components for advanced testing scenarios.
These contributions strengthen critical infrastructure within the Appium ecosystem and demonstrate LambdaTest's commitment to deep technical involvement in the project's evolution.
**About LambdaTest**
LambdaTest’s platform already serves a massive community of Appium users. As a GenAI-powered Quality Engineering Platform, they provide a full-stack testing cloud with 10,000+ real mobile devices and 3,000+ browsers.
Beyond standard infrastructure, they are pushing the boundaries of test execution with AI-native test management and next-generation agents like KaneAI. By supporting Appium alongside Selenium, Playwright, and other major frameworks, LambdaTest helps teams orchestrate intelligent automation at cloud scale.
LambdaTest will continue contributing people, code, and development expertise to strengthen Appium's core functionality. Their commitment represents a significant investment into the future of the framework, and we're thrilled to have them collaborating with us at this deeper level.
The Appium project is proud to recognize LambdaTest as our newest official Development Partner. We can't wait to see what we'll build together!
@@ -1,42 +0,0 @@
---
authors:
- jlipps
date: 2025-07-01
---
# Announcing LambdaTest as Appium Strategic Partner
After recently celebrating the 1-year anniversary of our [Sponsorship Program and Compensation
Scheme](https://appium.io/docs/en/latest/blog/2024/05/14/announcing-appiums-sponsorship-program/),
the Appium project is very excited to announce that <a
href="https://lambdatest.com/?utm_source=appium.io&utm_medium=organic&utm_campaign=june_25&utm_term=sk&utm_content=webpage">LambdaTest</a>
is coming on board as one of our Strategic Partners!
<!-- more -->
<div style="text-align:center;width:100%">
<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="300" />
<img src="/docs/en/latest/assets/images/sponsor-logo-lambdatest-light.png#only-light" width="300" />
</a>
</div>
Having long been active in the Appium community and the automated testing industry, LambdaTest is
now significantly stepping up their investment into these areas. With the decision to come on board
as a Strategic Partner, LambdaTest will support the Appium project through financial contribution
as well as contribution of code and project maintenance. Obviously, without the generous support of
partners like LambdaTest, we would not be able to continue our contributor compensation scheme,
which has seen the release of a substantial amount of funds to Appium maintainers and contributors
over the last year. Thanks again to LambdaTest, and stay tuned for more collaboration updates
throughout the year!
**About LambdaTest**
<em>LambdaTest is a GenAI-powered Quality Engineering Platform that empowers teams to test
intelligently, smarter, and ship faster. Built for scale, it offers a full-stack testing cloud with
10K+ real mobile devices and 3,000+ browsers. With AI-native test management, MCP servers, and
agent-based automation, LambdaTest supports Selenium, Appium, Playwright, and all major frameworks.
AI Agents like HyperExecute and KaneAI bring the power of AI and cloud into your software testing
workflow, enabling seamless automation testing with 120+ integrations. LambdaTest Agents accelerate
your testing throughout the entire SDLC, from test planning and authoring to automation,
infrastructure, execution, RCA, and reporting.</em>
@@ -1,38 +0,0 @@
---
authors:
- mykola
date: 2026-09-01
---
# Announcing watchOS Simulator Support in the XCUITest Driver
We’re excited to announce that the XCUITest driver now supports automation of watchOS apps — a
platform that’s been on Appium’s requested list for a long time.
<!-- more -->
In order to automate watchOS, you'll need the following:
* XCUITest driver version 12.6.0 or later (WebDriverAgent 16.5.0 or later)
* Xcode 15.4 or later
* watchOS 10 or later
Important to note: ^^the driver currently only works with simulators — real devices are not
compatible.^^
The good news: automating a watchOS app looks just like automating any other iOS/iPadOS app. The
standard use-cases of finding and clicking on elements, retrieving the page source, using the
Appium Inspector — all work as usual. The one exception here is standard W3C gesture/touch actions
(tap/swipe via the Actions API), which are not supported.
On top of that, a few watchOS-specific extensions are available:
- `mobile: pressButton` — press the Digital Crown or Action button
- `mobile: rotateDigitalCrown` — rotate the Digital Crown (since driver version 12.7.0)
- `mobile: performHandGesture` — perform double-tap or wrist flick hand gestures (since driver
version 12.7.0)
For full setup instructions, capabilities, and limitations, check out the
[watchOS guide](https://appium.github.io/appium-xcuitest-driver/latest/guides/watchos/).
Happy testing!
@@ -1,40 +0,0 @@
---
authors:
- sai
- srini
- jlipps
date: 2025-08-07
---
# 🚀 Appium 3
Appium 3 is here — and while it's not as massive a leap as Appium 2, it introduces a few essential
breaking changes that developers and QA engineers should be aware of.
<!-- more -->
The main idea behind Appium 3 is to clear out old cruft so that Appium can be leaner moving
forward, and rely on newer versions of software with better performance and security
characteristics. We're also getting rid of legacy behaviors and protocols that we deprecated as
part of Appium 2.
For you as a user, there's not much to worry about. The breaking changes are minimal:
- Node.js / NPM minimum version bump (to 20.19 / 10)
- Removal of certain deprecated endpoints
- Security feature flag prefix requirements (e.g. `adb_shell` to `uiautomator2:adb_shell`)
In terms of new features, we've been adding them incrementally rather than saving them up for
Appium 3. But with this release we are excited to share these new capabilities:
- `appium plugin install inspector` (Use Appium to host the Inspector rather than downloading it as a separate app)
- Clients can set the `X-Appium-Is-Sensitive` HTTP header on requests to direct the server to mask the data in the request in the logs, so that when you send a password into an input box, the password's actual value is not logged in plaintext. ([Learn more](../../developing/sensitive.md))
Of course, we have a full [Appium 3 migration guide](../../guides/migrating-2-to-3.md) to make sure
you know all the details and can deeply understand the consequences of upgrading to Appium 3 in
your environment.
---
**Ready to make the leap?** Appium 3 is a great step forward in creating more secure, maintainable,
and W3C-compliant test automation pipelines. Happy testing!
+70
View File
@@ -0,0 +1,70 @@
---
hide:
- toc
title: Server Command-Line Arguments
---
To start the Appium server, you may either run `appium` or `appium server`. The `server` subcommand
is considered to be the default, so if you omit it, Appium will interpret this as your request to
run the Appium server.
The invocation of `appium` (or `appium server`) can take a number of arguments, which are detailed
below.
!!! note
All of these arguments can be set via a [Configuration File](../guides/config.md) instead if
you want. Any arguments set on the command line will override any arguments found in
a configuration file.
|<div style="width:12em">Argument</div>|Description|Type|<div style="width:8em">Default</div>|Aliases|
|--|--|--|--|--|
|`--address`|IP address to listen on|string|`0.0.0.0`|`-a`|
|`--allow-cors`|Whether the Appium server should allow web browser connections from any host|boolean|`false`||
|`--allow-insecure`|Set which insecure features are allowed to run in this server's sessions. Features are defined on a driver level; see documentation for more details. Note that features defined via `--deny-insecure` will be disabled, even if also listed here. If string, a path to a text file containing policy or a comma-delimited list.|array<string>|`[]`||
|`--base-path`|Base path to use as the prefix for all webdriver routes running on the server|string|`""`|`-pa`|
|`--callback-address`|Callback IP address (default: same as `--address`)|string||`-ca`|
|`--callback-port`|Callback port (default: same as `--port`) (Value must be between `1` and `65535`)|integer|`4723`|`-cp`|
|`--config`|Path to an [Appium configuration JSON file](../guides/config.md)|string|||
|`--debug-log-spacing`|Add exaggerated spacing in logs to help with visual inspection|boolean|`false`||
|`--default-capabilities`|Set the default desired capabilities, which will be set on each session unless overridden by received capabilities. If a string, a path to a JSON file containing the capabilities, or raw JSON.|object||`-dc`|
|`--deny-insecure`|Set which insecure features are not allowed to run in this server's sessions. Features are defined on a driver level; see documentation for more details. Features listed here will not be enabled even if also listed in `--allow-insecure`, and even if `--relaxed-security` is enabled. If string, a path to a text file containing policy or a comma-delimited list.|array<string>|`[]`||
|`--driver`|Driver-specific configuration. Keys should correspond to driver package names|object|||
|`--drivers-import-chunk-size`|The maximum amount of drivers that could be imported in parallel on server startup|number|`3`||
|`--keep-alive-timeout`|Number of seconds the Appium server should apply as both the keep-alive timeout and the connection timeout for all requests. Setting this to `0` disables the timeout.|integer|`600`|`-ka`|
|`--request-timeout`|Number of seconds the Appium server should apply for receiving the entire HTTP request from the client. A value of 0 disables the timeout. Set it to a non-zero value to protect against potential Denial-of-Service attacks in case the server is deployed without a reverse proxy in front. HTTP requests that are running longer than allowed by this timeout would be rejected with the status code 408.|integer|`3600`||
|`--local-timezone`|Use local timezone for timestamps|boolean|`false`||
|`--log`|Also send log output to this file|string||`-g`|
|`--log-filters`|One or more log filtering rules|array|||
|`--log-level`|Log level (console[:file]) (Value must be one of: `info`, `info:debug`, `info:info`, `info:warn`, `info:error`, `warn`, `warn:debug`, `warn:info`, `warn:warn`, `warn:error`, `error`, `error:debug`, `error:info`, `error:warn`, `error:error`, `debug`, `debug:debug`, `debug:info`, `debug:warn`, `debug:error`)|string|`debug`||
|`--log-format`|Log format (Value must be to one of: `text`, `json`, `pretty_json`). If logs are printed as JSON then the text coloring is always disabled.|string|`text`||
|`--log-no-colors`|Do not use color in console output|boolean|`false`||
|`--log-timestamp`|Show timestamps in console output|boolean|`false`||
|`--long-stacktrace`|Add long stack traces to log entries. Recommended for debugging only.|boolean|`false`||
|`--no-perms-check`|Skip various permission checks on the server startup|boolean|`false`||
|`--nodeconfig`|Path to configuration JSON file to register Appium as a node with Selenium Grid 3; otherwise the configuration itself|string|||
|`--plugin`|Plugin-specific configuration. Keys should correspond to plugin package names|object|||
|`--plugins-import-chunk-size`|The maximum amount of plugins that could be imported in parallel on server startup|number|`7`||
|`--port`|Port to listen on (Value must be between `1` and `65535`)|integer|`4723`|`-p`|
|`--relaxed-security`|Disable additional security checks, so it is possible to use some advanced features, provided by drivers supporting this option. Only enable it if all the clients are in the trusted network and it's not the case if a client could potentially break out of the session sandbox. Specific features can be overridden by using `--deny-insecure`|boolean|`false`||
|`--session-override`|Enables session override (clobbering)|boolean|`false`||
|`--ssl-cert-path`|Absolute path to the `.cert` file if TLS is used. Must be provided together with `--ssl-key-path`. See the [SSL/TLS/SPDY Support guide](../guides/tls.md) for details|string|||
|`--ssl-key-path`|Absolute path to the `.key` file if TLS is used. Must be provided together with `--ssl-cert-path`. See the [SSL/TLS/SPDY Support guide](../guides/tls.md) for details|string|||
|`--strict-caps`|Cause sessions to fail if desired caps are sent in that Appium does not recognize as valid for the selected device|boolean|`false`||
|`--tmp`|Absolute path to directory Appium can use to manage temp files|string|Windows: `C:\Windows\Temp`<br>Others: `/tmp`||
|`--trace-dir`|Absolute path to directory Appium can use to save iOS instrument traces|string|`<tmp>/appium-instruments`||
|`--use-drivers`|A list of drivers to activate. By default, all installed drivers will be activated.|array<string>|`[]`||
|`--use-plugins`|A list of plugins to activate. To activate all plugins, the value should be an array with a single item `"all"`.|array<string>|`[]`||
|`--webhook`|Also send log output to this http listener|string||`-G`|
The following arguments are used for information retrieval, after which the server will automatically exit. They are therefore meant for reference or debug purposes.
|<div style="width:10em">Argument</div>|Description|Alias|
|--|--|--|
|`--help`|Print instructions on using the Appium command-line. This argument can also be used for any Appium subcommands.|`-h`|
|`--show-build-info`|Print detailed information on the Appium server version||
|`--show-config`|Print the current Appium server configuration details||
|`--show-debug-info`|Print information on the current environment: details about the operating system, Node.js, and Appium itself||
|`--version`|Print the Appium server version|`-v`|
+24
View File
@@ -0,0 +1,24 @@
---
hide:
- toc
title: Server Environment Variables
---
The primary way of configuring the Appium server is via [Command-Line Arguments](./args.md). However, some more
advanced features are toggled or configured via environment variables. To set environment
variables, refer to the documentation for your operating system and terminal. These are the
environment variables that the Appium server understands:
|Variable&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|Description|
|--------|-----------|
|`APPIUM_HOME`|By default, Appium creates a directory called `.appium` in the home directory for your system user. You can adjust the directory with this variable, as detailed in the [Managing Extensions](../guides/managing-exts.md) guide.|
|`APPIUM_TMP_DIR`|By default, Appium uses a random temporary directory for many of its operations. If you wish to use a specific directory, you may do so by including an absolute path as the value of this variable. The behaviour is equivalent to using the `--tmp` CLI arg.|
|`APPIUM_PREFER_SYSTEM_UNZIP`|Set to `0` or `false` to request that Appium not use the `unzip` binary included on your system for unzipping downloaded apps or other artifacts. Instead it will use a JS-based unzip library. This could help on some systems with non-existent or non-standard `unzip` commands. Note that if unzipping fails using the system library, the fallback library will be attempted in any case, so setting this env var merely saves time in the event you know the system unzip will fail.|
|`APPIUM_HOST`|Same as the `--address` CLI arg|
|`APPIUM_PORT`|Same as the `--port` CLI arg|
|`APPIUM_RELOAD_EXTENSIONS`|Set to `1` to cause Appium to re-require extensions when new sessions are created. This is mostly useful for [building extensions](../developing/build-drivers.md)|
|`APPIUM_OMIT_PEER_DEPS`|Adds `--omit=peer` to all the NPM commands run internally by Appium. Mostly an internal feature.|
|`APPIUM_APPS_CACHE_MAX_AGE`|Allows to set the maximum age (in minutes) for [cached applications](../guides/caching.md). The default value is `60 * 24` (24 hours). Do not set it to a lower number than the duration of a single session startup.|
|`APPIUM_APPS_CACHE_MAX_ITEMS`|Allows to set the maximum amount of [cached applications](../guides/caching.md). The default value is `1024`. Do not set it to a lower number than the amount of apps in all parallel sessions per process.|
|`APPIUM_APPS_CACHE_IGNORE_URL_QUERY`| If the above option is enabled then the 'search' part of the app URL will be cut off from cache keys. See the corresponding [feature request](https://discuss.appium.io/t/regarding-app-caching-when-using-aws-s3-presigned-urls/42713) for more details. Disabled by default.|
+226
View File
@@ -0,0 +1,226 @@
---
title: Extension Command-Line Usage
---
Appium allows for the flexible installation and management of various _extensions_, such as _drivers_
(which provide Appium with the capability to automate a given platform) and _plugins_ (which can
augment or alter the way individual Appium commands work). For a conceptual understanding of these
entities, please review the [Introduction](../intro/index.md).
Management of drivers and plugins is handled by Appium's Extension CLI (command-line interface).
!!! note
This reference uses placeholders to refer to various options. Anywhere you see one of these
placeholders in the reference, ensure you replace it with the correct type of actual content.
|Placeholder|Meaning|
|--|--|
|`<ext-type>`|"Extension type". It should be either `driver` or `plugin`. All the Extension CLI commands can be used with either drivers or plugins, so you must specify which type of extension will be used|
|`<ext-name>`|"Extension name". This is the short name of the extension found in a call to `appium <ext-type> list`. This is distinct from the NPM package name of the extension or, in general, the "install spec" of the extension.|
|`<install-spec>`|"Install specification". This refers to the string used to indicate what extension Appium should install.|
|`<install-source>`|This refers to the method that Appium should use to install an extension.|
## Commands
All Extension CLI commands begin with `appium <ext-type>`, i.e., either `appium driver` or `appium
plugin`.
All Extension CLI commands can take an optional `--json` argument, which will return the result of
the command as a machine-readable JSON string rather than the standard output, which is colourized
and tuned for human consumption.
### `doctor`
Run doctor checks for the given extension, which validate whether the extension has its prerequisites
configured correctly. Note that not all extensions include doctor checks. See the
[Building Doctor Checks](../developing/build-doctor-checks.md) tutorial for more details on
how to create them.
Usage:
```
appium <ext-type> doctor <ext-name>
```
Required arguments:
- `<ext-type>`: must be `driver` or `plugin`
- `<ext-name>`: the name of the extension whose doctor checks you want to run
Optional arguments:
- `--json`: return the result in JSON format
Example (run doctor checks for the UiAutomator2 driver):
```
appium driver doctor uiautomator2
```
### `install`
Install an extension. If successful, respond with the short name of the extension which can be used
in other invocations of the Extension CLI. If the extension is a driver, also note which platforms
may be used with the driver.
Usage:
```
appium <ext-type> install <install-spec> [--source=<install-source>] [--package=<package-name>] [--json]
```
Required arguments:
- `<ext-type>`: must be `driver` or `plugin`
- `<install-spec>`: this is the name, location, and/or version of the extension you want to
install. Its possible values are dependent on the `<install-source>` (see below).
Optional arguments:
- `--source`: this directs Appium where to find your extension. See below for a table of possible
source types and corresponding install specification.
- `--package`: when `<install-source>` is `git` or `github`, `--package` is required. It should be
the Node.js package name of the extension. Without this information, Appium will not be able to
find the installed package.
- `--json`: return the result in JSON format
|Install source type|Behaviour|
|--|--|
|None|This is the default behaviour when no `--source` is used. In this case, Appium will look at `<install-spec>` and match it against the name of extensions available when running `appium <ext-type> list`, i.e., against the officially recognized extension names. If found, it will install that extension at the latest version via NPM|
|`npm`|Install an extension based on its NPM package name. Here, `<install-spec>` must be the NPM package name with any additional NPM installation modifiers, like version (see below)|
|`github`|Install an extension via a GitHub spec of the form `<org>/<repo>`|
|`git`|Install an extension via a Git URL (e.g., `git+ssh://git-host.com/repo.git`)|
|`local`|Install an extension via a local path. This must be a path to the directory where the Node.js package information for the driver is located.|
#### NPM-based `<install-spec>`
When Appium is installing an extension via NPM (as is the case when `--source` is either omitted or
set to `npm`), the `<install-spec>` can be complex, and can include any kind of information allowed
by `npm install`:
- `[@scope]/<name>`
- `[@scope]/<name>@<version>`
- `[@scope]/<name>@<tag>`
- `[@scope]/<name>@<version range>`
#### Examples
- Install the latest XCUITest driver:
```
appium driver install xcuitest
```
- Install the XCUITest driver at version 4.11.1:
```
appium driver install xcuitest@4.11.1
```
- Install the `beta` version of the `@appium/fake-driver` from NPM:
```
appium driver install --source=npm @appium/fake-driver@beta
```
- Install a locally-developed plugin:
```
appium plugin install --source=local /path/to/my/plugin
```
### `list`
List installed and available extensions. "Available" extensions include those which are officially
recognized by the Appium team, but you are not limited to installing only the extensions displayed
in this list.
Usage:
```
appium <ext-type> list [--installed] [--updates] [--json]
```
Required arguments:
- `<ext-type>`: must be `driver` or `plugin`
Optional arguments:
- `--installed`: show only installed extensions, not installed plus available extensions
- `--updates`: for extensions installed via NPM, display a message if there are any updates
- `--json`: return the result in JSON format
### `run`
Run a script included in an extension package. Extension authors can include runnable scripts that
assist with setup or perform other tasks. These scripts are given names (called the `<script-name>`
in this reference) by extension authors and will generally be documented in extension
documentation.
Usage:
```
appium <ext-type> run <ext-name> [--json] <script-name> [script-args]
```
Required arguments:
- `<ext-type>`: must be `driver` or `plugin`
- `<ext-name>`: the name of the extension whose script you want to run
- `<script-name>`: the name of the script the extension has published
Optional arguments:
- `script-args`: any arguments that Appium does not interpret as belonging to its own set of
arguments will be passed along to the extension script
- `--json`: return the result in JSON format
Example (run the `reset` script included with the UiAutomator2 driver):
```
appium driver run uiautomator2 reset
```
### `update`
Update one or more extensions that have been installed via NPM. By default, Appium will not
automatically update any extension past a major version boundary, so as to prevent
unintended breaking changes.
Usage:
```
appium <ext-type> update <ext-name> [--unsafe] [--json]
```
Required arguments:
- `<ext-type>`: must be `driver` or `plugin`
- `<ext-name>`: the name of the extension to update, or the string `installed` (which will update
all installed extensions)
Optional arguments:
- `--unsafe`: direct Appium to go ahead and update past a major version boundary
- `--json`: return the result in JSON format
### `uninstall`
Remove an installed extension.
Usage:
```
appium <ext-type> uninstall <ext-name> [--json]
```
Required arguments:
- `<ext-type>`: must be `driver` or `plugin`
- `<ext-name>`: the name of the extension to uninstall
Optional arguments:
- `--json`: return the result in JSON format
+26
View File
@@ -0,0 +1,26 @@
---
hide:
- toc
title: Command-Line Overview
---
Appium provides a command-line executable (`appium`), which will likely be your main way of interacting with
the Appium server. This section of the Appium documentation describes how to use this executable.
To start off, you can run `appium -v` or `appium --version` to return the installed version,
or run `appium -h` or `appium --help` to return the help message.
The main `appium` executable provides the following subcommands:
1. `appium server` (or simply `appium`) - launch an Appium server
- [See here for accepted arguments](./args.md)
- For advanced features, [see here for accepted environment variables](./env-vars.md)
2. `appium driver` - manage Appium drivers
- [See here for details](./extensions.md)
3. `appium plugin` - manage Appium plugins
- [See here for details](./extensions.md)
4. `appium setup` - batch install a preset of drivers and plugins
- [See here for details](./setup.md)
Like the main command, you can also run each subcommand with the `-h` or `--help` flag to learn more about it.
+33
View File
@@ -0,0 +1,33 @@
---
hide:
- toc
title: Setup Command-Line Usage
---
The `setup` command aims to simplify the initial procedure of setting up Appium. It allows to install
multiple extensions (drivers/plugins) in one go, without the need to run
`appium <ext-name> install <ext-name>` multiple times.
The command has several presets that can be used to install different sets of extensions.
The presets are as follows:
|Preset|Installation Command|Included Drivers|Included Plugins|
|--|--|--|--|
|Mobile|`appium setup mobile` or `appium setup`|`uiautomator2`, `xcuitest`[^1], `espresso`|`images`|
|Desktop application|`appium setup desktop`|`mac2`[^1], `windows`[^2]|`images`|
|Desktop browser|`appium setup browser`|`safari`[^1], `gecko`, `chromium`|`images`|
Attempting to install a preset while already having one or more of its included extensions installed
will only install the missing extensions.
Refer to the [Ecosystem documentation](../ecosystem/index.md) to learn more about the extensions
listed above.
This commands also supports the functionality that allows to fully reset your Appium server
deployment if you experience various configuration issues,
for example, due to a failed upgrade attempt from an older Appium version, on server startup.
By running `appium setup reset` the server would uninstall all installed drivers, plugins and their related manifest files from the currently used Appium home folder.
[^1]: Only installed if the host machine is running macOS.
[^2]: Only installed if the host machine is running Windows.
@@ -0,0 +1,562 @@
# Driver: base-driver
### `createSession`
`POST` **`/session`**
Historically the first two arguments were reserved for JSONWP capabilities.
Appium 2 has dropped the support of these, so now we only accept capability
objects in W3C format and thus allow any of the three arguments to represent
the latter.
**`See`**
[https://w3c.github.io/webdriver/#new-session](https://w3c.github.io/webdriver/#new-session)
<!-- comment source: multiple -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `desiredCapabilities?` | `W3CDriverCaps`<`C`\> | the new session capabilities |
| `requiredCapabilities?` | `W3CDriverCaps`<`C`\> | another place the new session capabilities could be sent (typically left undefined) |
| `capabilities?` | `W3CDriverCaps`<`C`\> | another place the new session capabilities could be sent (typically left undefined) |
#### Response
`CreateResult`
The capabilities object representing the created session
### `deleteSession`
`DELETE` **`/session/:sessionId`**
Returns capabilities for the session and event history (if applicable)
<!-- comment source: method-signature -->
#### Response
`SingularSessionData`<`C`, `SessionData`\>
A session data object
### `getSession`
`GET` **`/session/:sessionId`**
Returns capabilities for the session and event history (if applicable).
!!! warning "Deprecated"
Please use `getAppiumSessionCapabilities` to get the session capabilities.
Please use `getLogEvents` to get event history.
<!-- comment source: multiple -->
#### Response
`SingularSessionData`<`C`, `SessionData`\>
A session data object
### `getAppiumSessionCapabilities`
`GET` **`/session/:sessionId/appium/capabilities`**
Returns capabilities for the session.
<!-- comment source: multiple -->
#### Response
`AppiumSessionCapabilities`
A session data object
### `findElement`
`POST` **`/session/:sessionId/element`**
Find a UI element given a locator strategy and a selector, erroring if it can't be found
**`See`**
[https://w3c.github.io/webdriver/#find-element](https://w3c.github.io/webdriver/#find-element)
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `using` | `string` | the locator strategy |
| `value` | `string` | the selector to combine with the strategy to find the specific element |
#### Response
`Element`<`string`\>
The element object encoding the element id which can be used in element-related
commands
### `findElementFromElement`
`POST` **`/session/:sessionId/element/:elementId/element`**
Find a UI element given a locator strategy and a selector, erroring if it can't be found. Only
look for elements among the set of descendants of a given element
**`See`**
[https://w3c.github.io/webdriver/#find-element-from-element](https://w3c.github.io/webdriver/#find-element-from-element)
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `using` | `string` | the locator strategy |
| `value` | `string` | the selector to combine with the strategy to find the specific element |
#### Response
`Element`<`string`\>
The element object encoding the element id which can be used in element-related
commands
### `findElementFromShadowRoot`
`POST` **`/session/:sessionId/shadow/:shadowId/element`**
Find an element from a shadow root
**`See`**
[https://w3c.github.io/webdriver/#find-element-from-shadow-root](https://w3c.github.io/webdriver/#find-element-from-shadow-root)
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `using` | `string` | the locator strategy |
| `value` | `string` | the selector to combine with the strategy to find the specific elements |
#### Response
`Element`<`string`\>
The element inside the shadow root matching the selector
### `findElements`
`POST` **`/session/:sessionId/elements`**
Find a a list of all UI elements matching a given a locator strategy and a selector
**`See`**
[https://w3c.github.io/webdriver/#find-elements](https://w3c.github.io/webdriver/#find-elements)
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `using` | `string` | the locator strategy |
| `value` | `string` | the selector to combine with the strategy to find the specific elements |
#### Response
`Element`<`string`\>[]
A possibly-empty list of element objects
### `findElementsFromElement`
`POST` **`/session/:sessionId/element/:elementId/elements`**
Find a a list of all UI elements matching a given a locator strategy and a selector. Only
look for elements among the set of descendants of a given element
**`See`**
[https://w3c.github.io/webdriver/#find-elements-from-element](https://w3c.github.io/webdriver/#find-elements-from-element)
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `using` | `string` | the locator strategy |
| `value` | `string` | the selector to combine with the strategy to find the specific elements |
#### Response
`Element`<`string`\>[]
A possibly-empty list of element objects
### `findElementsFromShadowRoot`
`POST` **`/session/:sessionId/shadow/:shadowId/elements`**
Find elements from a shadow root
**`See`**
[https://w3c.github.io/webdriver/#find-element-from-shadow-root](https://w3c.github.io/webdriver/#find-element-from-shadow-root)
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `using` | `string` | the locator strategy |
| `value` | `string` | the selector to combine with the strategy to find the specific elements |
#### Response
`Element`<`string`\>[]
A possibly empty list of elements inside the shadow root matching the selector
### `getLog`
`POST` **`/session/:sessionId/log`**
Get the log for a given log type.
!!! warning "Deprecated"
Please use the `/session/:sessionId/se/log` endpoint instead
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `type` | `string` | Name/key of log type as defined in ILogCommands.supportedLogTypes. |
#### Response
`any`
### `getLog`
`POST` **`/session/:sessionId/se/log`**
Get the log for a given log type.
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `type` | `string` | Name/key of log type as defined in ILogCommands.supportedLogTypes. |
#### Response
`any`
### `getLogEvents`
`POST` **`/session/:sessionId/appium/events`**
Get a list of events that have occurred in the current session
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `type?` | `string` \| `string`[] | filter the returned events by including one or more types |
#### Response
`EventHistory` \| `Record`<`string`, `number`\>
The event history for the session
### `getLogTypes`
`GET` **`/session/:sessionId/log/types`**
Get available log types as a list of strings
!!! warning "Deprecated"
Please use the `/session/:sessionId/se/log/types` endpoint instead
<!-- comment source: method-signature -->
#### Response
`string`[]
### `getLogTypes`
`GET` **`/session/:sessionId/se/log/types`**
Get available log types as a list of strings
<!-- comment source: method-signature -->
#### Response
`string`[]
### `getPageSource`
`GET` **`/session/:sessionId/source`**
Get the current page/app source as HTML/XML
**`See`**
[https://w3c.github.io/webdriver/#get-page-source](https://w3c.github.io/webdriver/#get-page-source)
<!-- comment source: method-signature -->
#### Response
`string`
The UI hierarchy in a platform-appropriate format (e.g., HTML for a web page)
### `getSessions`
`GET` **`/sessions`**
Get data for all sessions running on an Appium server
<!-- comment source: method-signature -->
#### Response
A list of session data objects.
Each session data object will be returned with `id` and the session's capabilities as `capabilities` keys like an example below:
```json
[
{
"id":"ba30c6da-c266-4734-8ddb-c16f5bb53e16",
"capabilities":{ "platformName":"ios","browserName":"safari","automationName":"xcuitest","platformVersion":"17.2","deviceName":"iPhone 15" }
},
{
"id":"1441110c-1ece-4e45-abbf-ebf404f45f0a",
"capabilities":{ "platformName":"ios","browserName":"safari","automationName":"xcuitest","platformVersion":"17.0","deviceName":"iPhone 14" }
},
...
]
```
### `getSettings`
`GET` **`/session/:sessionId/appium/settings`**
Update the session's settings dictionary with a new settings object
<!-- comment source: method-signature -->
#### Response
``null``
### `updateSettings`
`POST` **`/session/:sessionId/appium/settings`**
Update the session's settings dictionary with a new settings object
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `settings` | `Settings` | A key-value map of setting names to values. Settings not named in the map will not have their value adjusted. |
#### Response
``null``
### `getStatus`
`GET` **`/status`**
**`Summary`**
Retrieve the server's current status.
**`Description`**
Returns information about whether a remote end is in a state in which it can create new sessions and can additionally include arbitrary meta information that is specific to the implementation.
The readiness state is represented by the ready property of the body, which is false if an attempt to create a session at the current time would fail. However, the value true does not guarantee that a New Session command will succeed.
Implementations may optionally include additional meta information as part of the body, but the top-level properties ready and message are reserved and must not be overwritten.
<!-- comment source: builtin-interface -->
#### Examples
<!-- BEGIN:EXAMPLES -->
##### JavaScript
<!-- BEGIN:EXAMPLE lang=JavaScript -->
```js
// webdriver.io example
await driver.status();
```
<!-- END:EXAMPLE -->
##### Python
<!-- BEGIN:EXAMPLE lang=Python -->
```python
driver.get_status()
```
<!-- END:EXAMPLE -->
##### Java
<!-- BEGIN:EXAMPLE lang=Java -->
```java
driver.getStatus();
```
<!-- END:EXAMPLE -->
##### Ruby
<!-- BEGIN:EXAMPLE lang=Ruby -->
```ruby
# ruby_lib example
remote_status
# ruby_lib_core example
@driver.remote_status
```
<!-- END:EXAMPLE -->
<!-- END:EXAMPLES -->
#### Response
`Object`
### `getTimeouts`
`GET` **`/session/:sessionId/timeouts`**
Set the various timeouts associated with a session
**`See`**
[https://w3c.github.io/webdriver/#set-timeouts](https://w3c.github.io/webdriver/#set-timeouts)
<!-- comment source: method-signature -->
#### Response
``null``
### `timeouts`
`POST` **`/session/:sessionId/timeouts`**
Set the various timeouts associated with a session
**`See`**
[https://w3c.github.io/webdriver/#set-timeouts](https://w3c.github.io/webdriver/#set-timeouts)
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `type?` | `string` | used only for the old (JSONWP) command, the type of the timeout |
| `ms?` | `string` \| `number` | used only for the old (JSONWP) command, the ms for the timeout |
| `script?` | `number` | the number in ms for the script timeout, used for the W3C command |
| `pageLoad?` | `number` | the number in ms for the pageLoad timeout, used for the W3C command |
| `implicit?` | `string` \| `number` | the number in ms for the implicit wait timeout, used for the W3C command |
#### Response
``null``
### `implicitWait`
`POST` **`/session/:sessionId/timeouts/implicit_wait`**
Set the implicit wait timeout
!!! warning "Deprecated"
Please use the `/session/:sessionId/timeouts` endpoint instead
Use `timeouts` instead
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `ms` | `string` \| `number` | the timeout in ms |
#### Response
``null``
### `logCustomEvent`
`POST` **`/session/:sessionId/appium/log_event`**
Add a custom-named event to the Appium event log
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `vendor` | `string` | the name of the vendor or tool the event belongs to, to namespace the event |
| `event` | `string` | the name of the event itself |
#### Response
``null``
### `reset`
`POST` **`/session/:sessionId/appium/app/reset`**
Reset the current session (run the delete session and create session subroutines)
!!! warning "Deprecated"
Please use each driver's launch, activate, terminate or cleanup method.
Use explicit session management commands instead
<!-- comment source: method-signature -->
#### Response
``null``
@@ -0,0 +1,22 @@
# Plugin: execute-driver
### `executeDriverScript`
`POST` **`/session/:sessionId/appium/execute_driver`**
Implementation of a command within a plugin
At minimum, `D` must be `ExternalDriver`, but a plugin can be more narrow about which drivers it supports.
<!-- comment source: method-signature -->
#### Parameters
| Name | Type |
| :------ | :------ |
| `script` | [script: string, scriptType: string, timeoutMs: number] |
| `type?` | [script: string, scriptType: string, timeoutMs: number] |
#### Response
`unknown`
@@ -0,0 +1,89 @@
# Plugin: images
### `compareImages`
`POST` **`/session/:sessionId/appium/compare_images`**
#### Parameters
| Name | Type |
| :------ | :------ |
| `mode` | `any`[] |
| `options?` | `any`[] |
#### Response
`ComparisonResult`
### `findElement`
`POST` **`/session/:sessionId/element`**
Find a UI element given a locator strategy and a selector, erroring if it can't be found
**`See`**
[https://w3c.github.io/webdriver/#find-element](https://w3c.github.io/webdriver/#find-element)
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `using` | `any` | the locator strategy |
| `value` | `any` | the selector to combine with the strategy to find the specific element |
#### Response
`any`
The element object encoding the element id which can be used in element-related
commands
### `findElements`
`POST` **`/session/:sessionId/elements`**
Find a a list of all UI elements matching a given a locator strategy and a selector
**`See`**
[https://w3c.github.io/webdriver/#find-elements](https://w3c.github.io/webdriver/#find-elements)
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `using` | `any` | the locator strategy |
| `value` | `any` | the selector to combine with the strategy to find the specific elements |
#### Response
`any`
A possibly-empty list of element objects
### `performActions`
`POST` **`/session/:sessionId/actions`**
If the actions contains image elements as origin, convert them to viewport coordinates before sending it to the external driver
**`See`**
[https://w3c.github.io/webdriver/#perform-actions](https://w3c.github.io/webdriver/#perform-actions)
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `actions` | `ActionSequence[]` | an array of action sequences |
#### Response
`null`
+25
View File
@@ -0,0 +1,25 @@
---
hide:
- toc
title: Intro to Commands
---
Here you can find various commands exposed by the main Appium module through its base driver, as
well as the commands available in several plugins.
!!! note
The Appium base driver only exposes a few commands, as it is not meant to be used on its own.
Please refer to the documentation of your [Appium driver](../ecosystem/drivers.md) to learn
about the commands it exposes, and then check your [Appium client](../ecosystem/clients.md)
documentation for the exact syntax of that command.
The command listings can be found here:
* [Base Driver](./base-driver.md)
* [Execute Driver Plugin](./execute-driver-plugin.md)
* [Images Plugin](./images-plugin.md)
* [Relaxed Caps Plugin](./relaxed-caps-plugin.md)
* [Storage Plugin](./storage-plugin.md)
* [Universal XML Plugin](./universal-xml-plugin.md)
@@ -0,0 +1,27 @@
# Plugin: relaxed-caps
### `createSession`
`POST` **`/session`**
Start a new automation session
**`See`**
[https://w3c.github.io/webdriver/#new-session](https://w3c.github.io/webdriver/#new-session)
<!-- comment source: multiple -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `desiredCapabilities?` | `any` | the new session capabilities |
| `requiredCapabilities?` | `any` | another place the new session capabilities could be sent (typically left undefined) |
| `capabilities?` | `any` | another place the new session capabilities could be sent (typically left undefined) |
#### Response
`any`
The capabilities object representing the created session
@@ -0,0 +1,113 @@
# Plugin: storage
!!! tip
All these commands can be invoked without creating a session, allowing you to
prepare your test environment in advance.
### `addStorageItem`
`POST` **`/storage/add`**
Add a new file to the storage
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `name` | `string` | the name used to save the file (must not include path separator characters) |
| `sha1` | `string` | SHA1 hash of the file to be uploaded |
#### Example
```bash
curl -X POST --header "Content-Type: application/json" --data '{"name":"app.ipa","sha1":"ccc963411b2621335657963322890305ebe96186"}' http://127.0.0.1:4723/storage/add
```
#### Response
`AddRequestResult`
A JSON object in the following format:
```json
{
"ws": {
"stream": "/storage/add/ccc963411b2621335657963322890305ebe96186/stream",
"events": "/storage/add/ccc963411b2621335657963322890305ebe96186/events"
},
"ttlMs": 300000
}
```
| Name | Type | Description |
| :------ | :------ | :------ |
| `ws.stream` | `string` | the pathname of the streaming web socket used to upload the file content |
| `ws.events` | `string` | the pathname of the events web socket used to notify about upload success or a failure |
| `ttlMs` | `number` | the amount of milliseconds both web sockets will be kept active before they expire, or a file payload would be successfully uploaded |
### `listStorageItems`
`GET` **`/storage/list`**
List all files present in the storage
#### Example
```bash
curl http://127.0.0.1:4723/storage/list
```
#### Response
`List<StorageItem>`
A list of items, where each item has the following properties:
| Name | Type | Description |
| :------ | :------ | :------ |
| `name` | `string` | the name of the file in the storage |
| `path` | `string` | full path to the file on the remote file system |
| `size` | `number` | file size in bytes |
### `deleteStorageItem`
`POST` **`/storage/delete`**
Deletes a file in the storage with the specified name
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `name` | `string` | the name of the file to be deleted |
#### Example
```bash
curl -X POST --header "Content-Type: application/json" --data '{"name":"app.ipa"}' http://127.0.0.1:4723/storage/delete
```
#### Response
`boolean`
`false` if the file does not exist in the storage, or `true` upon successful file deletion
### `resetStorage`
`POST` **`/storage/reset`**
Deletes all uploaded files and stops any incomplete uploads.
If the `APPIUM_STORAGE_KEEP_ALL` flag is enabled, all uploaded files will be preserved,
and only the incomplete uploads will be stopped.
#### Example
```bash
curl -X POST http://127.0.0.1:4723/storage/reset
```
#### Response
`undefined`
@@ -0,0 +1,68 @@
# Plugin: universal-xml
### `findElement`
`POST` **`/session/:sessionId/element`**
Find a UI element given a locator strategy and a selector, erroring if it can't be found
**`See`**
[https://w3c.github.io/webdriver/#find-element](https://w3c.github.io/webdriver/#find-element)
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `using` | `any`[] | the locator strategy |
#### Response
`any`
The element object encoding the element id which can be used in element-related
commands
### `findElements`
`POST` **`/session/:sessionId/elements`**
Find a a list of all UI elements matching a given a locator strategy and a selector
**`See`**
[https://w3c.github.io/webdriver/#find-elements](https://w3c.github.io/webdriver/#find-elements)
<!-- comment source: method-signature -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| `using` | `any`[] | the locator strategy |
#### Response
`any`
A possibly-empty list of element objects
### `getPageSource`
`GET` **`/session/:sessionId/source`**
Get the current page/app source as HTML/XML
**`See`**
[https://w3c.github.io/webdriver/#get-page-source](https://w3c.github.io/webdriver/#get-page-source)
<!-- comment source: method-signature -->
#### Response
`string`
The UI hierarchy in a platform-appropriate format (e.g., HTML for a web page)
@@ -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/.github/blob/master/CODE_OF_CONDUCT.md).
participation is governed by our [Code of Conduct](https://github.com/appium/appium/blob/master/CONDUCT.md).
## Join the Discussion Forum
@@ -222,13 +222,18 @@ So you'll probably end up overriding `createSession`. You can do so by defining
driver:
```js
async createSession(w3cCaps) {
const [sessionId, caps] = await super.createSession(w3cCaps);
async createSession(jwpCaps, reqCaps, w3cCaps, otherDriverData) {
const [sessionId, caps] = super.createSession(w3cCaps);
// do your own stuff here
return [sessionId, caps];
}
```
For legacy reasons, your function will receive old-style JSON Wire Protocol desired and required
caps as the first two arguments. Given that the old protocol isn't supported anymore and clients
have all been updated, you can instead only rely on the `w3cCaps` parameter. (For a discussion
about what `otherDriverData` is about, see the section below on concurrent drivers).
You'll want to make sure to call `super.createSession` in order to get the session ID as well as
the processed capabilities (note that capabilities are also set on `this.caps`; modifying `caps`
locally here would have no effect other than changing what the user sees in the create session
@@ -515,13 +520,14 @@ route, then the route will not be proxied and instead will be handled by your dr
example, we are avoiding proxying all `POST` routes that have the `appium` prefix.
Next, we have to set up the proxying itself. The way to do this is to use a special class from
Appium called `WebDriverProxy`. You'll want to create a `WebDriverProxy` object using the details
required to connect to the remote server:
Appium called `JWProxy`. (The name means "JSON Wire Proxy" and is related to a legacy
implementation of the protocol). You'll want to create a `JWProxy` object using the details required to
connect to the remote server:
```js
// import {WebDriverProxy} from 'appium/driver';
// import {JWProxy} from 'appium/driver';
const proxy = new WebDriverProxy({
const proxy = new JWProxy({
server: 'remote.server',
port: 1234,
base: '/',
@@ -533,8 +539,8 @@ this.proxyCommand = proxy.command.bind(proxy);
Here we are creating a proxy object and assigning some of its methods to `this` under the names
`proxyReqRes` and `proxyCommand`. This is required for Appium to use the proxy, so don't forget
this step! The `WebDriverProxy` has a variety of other options [which you can check out in the
source code as well.](https://github.com/appium/appium/blob/master/packages/base-driver/lib/wd-proxy/proxy.ts)
this step! The `JWProxy` has a variety of other options which you can check out in the source code,
as well. (TODO: publish options as API docs and link here).
Finally, we need a way to tell Appium when the proxy is active. For your driver it might always
be active, or it might only be active when in a certain context. You can define the logic as an
@@ -562,33 +568,6 @@ 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
@@ -714,12 +693,6 @@ A couple notes about this system:
mode!
1. 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.
1. If your driver is written in TypeScript, declare the map `as const satisfies
ExecuteMethodMap<MyDriver>` (with `ExecuteMethodMap` imported from `@appium/types`). The
compiler then checks that each `command` names a method of your driver, and that the
`required`/`optional` params are consistent with that method's signature: the method must not
require a parameter which is listed as `optional` (or not listed at all), and must accept all
of the listed 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
@@ -794,32 +767,44 @@ that multiple simultaneous sessions don't use the same resources:
1. Have your users specify resource IDs via capabilities (`appium:driverPort` etc)
1. Just always use free resources (find a new random port for each session)
1. Have each running instance of your driver publish and subscribe to messages on a shared IPC
channel, so sessions can coordinate directly with one another.
1. Have each driver express what resources it is using, then examine currently-used resources from
other drivers when a new session begins.
The per-session IPC channel described in [Send messages to plugins running on the same
session](#send-messages-to-plugins-running-on-the-same-session) is isolated per session, so it
can't be used for this: it doesn't let you talk to *other* sessions of your driver. Instead,
construct and hold on to your own `AppiumIpc` instance (exported from `appium/driver.js`) at
module scope in your driver's package, for example as a memoized singleton. Since Node.js caches
modules, every instance of your driver loaded within the same Appium server process will share
that one `AppiumIpc` object, and can use it to publish and subscribe to topics across sessions —
the same way the per-session channel works, just not scoped to a single session. See
[xcuitest-driver's `session-claim-handler.ts`](https://github.com/appium/appium-xcuitest-driver/blob/master/lib/session-claim-handler.ts)
for a real example, which uses this technique to detect and resolve conflicting sessions targeting
the same device UDID.
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:
```js
get driverData() {
return {specialPort: 1234, specialFile: /path/to/file}
}
```
Now, when a new session is started on your driver, the `driverData` response from any other
simultaneously running drivers (of the same type) will also be included, as the last parameter of
the `createSession` method:
```js
async createSession(jwpCaps, reqCaps, w3cCaps, driverData)
```
You can dig into this `driverData` array to see what resources other drivers are using to help
determine which ones you want to use for this particular session.
!!! warning
This only works for sessions running within the same Node.js process (i.e. the same Appium
server). It cannot coordinate sessions running on different Appium server processes; for that,
consider file-based locking or a similar out-of-process mechanism.
Be careful here, since `driverData` is only passed between sessions of a single running Appium
server. There's nothing to stop a user from running multiple Appium servers and requesting your
driver simultaneously on each of them. In this case, you won't be able to ensure independence
of resources via `driverData`, so you might consider using file-based locking mechanisms or
something similar.
!!! warning
Appium also doesn't provide any features for ensuring unrelated drivers don't interfere with
one another, so it's up to the drivers to allow users to specify resource locations or
addresses to avoid clashes.
It's also important to note you will only receive `driverData` for other instances of *your*
driver. So unrelated drivers also running may still be using some system resources. In general
Appium doesn't provide any features for ensuring unrelated drivers don't interfere with one
another, so it's up to the drivers to allow users to specify resource locations or addresses to
avoid clashes.
### Log events to the Appium event timeline
@@ -873,123 +858,3 @@ 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:
- The `ipcSubscribe` method (and the IPC channel it subscribes to) is only available once
`onIpcInit` has been called, at the end of the `createSession` flow. It cannot be used statically
or in `createSession` hooks
- The channel that `ipcSubscribe` gives you access to is scoped to the current session, and is
shared only with the plugins active in that same session (this is also to prevent drivers/plugins
from accessing or reading data sent on IPC channels in other sessions.) To coordinate across
multiple concurrent sessions of your own driver instead, see [Make itself aware of resources
other concurrent drivers are
using](#make-itself-aware-of-resources-other-concurrent-drivers-are-using).
- 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.
@@ -170,7 +170,7 @@ This is the most normal behavior for Appium plugins -- to modify or replace the
more commands that would normally be handled by the active driver. To override the default command
handling, you need to implement `async` methods in your class with the same name as the Appium
commands to be handled (just exactly how [drivers themselves are
implemented](./build-drivers.md#implement-webdriver-classic-commands)). Curious what command names there
implemented](./build-drivers.md#implement-webdriver-commands)). Curious what command names there
are? They are defined in the Appium base driver's
[routes.js](https://github.com/appium/appium-base-driver/blob/master/lib/protocol/routes.js) file,
and of course you can add more as defined in the next section.
@@ -257,7 +257,7 @@ throw new errors.NoSuchElementError();
### Log messages to the Appium log
You can always use `console.log`, of course, but Appium provides a nice logger for you as
`this.log` (it has `.info`, `.debug`, `.warn`, `.error` methods on it for differing log
`this.logger` (it has `.info`, `.debug`, `.log`, `.warn`, `.error` methods on it for differing log
levels). If you want to create an Appium logger outside of a plugin context (say in a script or
helper file), you can always construct your own too:
@@ -477,9 +477,9 @@ capability.
You probably don't normally need to update the Appium server object (which is an
[Express](https://expressjs.com/) server having already been
[configured](https://github.com/appium/appium/blob/master/packages/base-driver/lib/express/server.js)
in a variety of ways). But, for example, you could add new routes to the server to support your
plugin's requirements. To update the server you must implement the `static async updateServer`
method in your class. This method takes three parameters:
in a variety of ways). But, for example, you could add new Express middleware to the server to
support your plugin's requirements. To update the server you must implement the `static async
updateServer` method in your class. This method takes three parameters:
* `expressApp`: the Express app object
* `httpServer`: the Node HTTP server object
@@ -492,25 +492,6 @@ results you'll need to test! Warning: this should be considered an advanced feat
knowledge of Express, as well as the care not to do anything that could affect the operation of
other parts of the Appium server!
`updateServer` runs *after* Appium's own routes are registered, so `expressApp.use(...)` here
won't see requests to paths Appium already owns — Express matches middleware and routes in
registration order. For middleware that must see requests to those routes too (e.g. logging or
auth), use `httpServer.frontRouter` instead: Appium mounts this
[Router](https://expressjs.com/en/5x/api/router/) before any route is registered, so anything
attached to it — even from inside `updateServer` — still runs ahead of route matching. Note this
is still *after* Appium's own baseline middleware (CORS, WebSocket upgrade handling, body
parsing, etc.), so it won't see requests Appium itself has already rejected, e.g. a CORS
preflight failure or a body that failed to parse:
```js
static async updateServer(expressApp, httpServer, cliArgs) {
httpServer.frontRouter.use((req, res, next) => {
console.log(`Incoming request: ${req.method} ${req.url}`);
next();
});
}
```
### Handle unexpected session shutdown
When developing a plugin you may want to add some cleanup logic for when a session ends. You would
@@ -531,12 +512,3 @@ 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.
@@ -2,8 +2,8 @@
title: Appium's Config System
---
Appium includes support for [configuration files](../guides/config.md). A configuration file is
intended to have (nearly) 1:1 parity with command-line arguments. An end user can supply Appium with
Appium 2 supports [configuration files](../guides/config.md). A configuration file is intended to
have (nearly) 1:1 parity with command-line arguments. An end user can supply Appium 2 with
a configuration file, CLI args, or both (the args have precedence over the config file).
This document will be a technical overview of how the configuration system works. It is intended
@@ -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/bootstrap/config-file.js` to load and/or search for a configuration file and in
will call into `lib/config-file.js` to load and/or search for a configuration file and in
`package.json`.
!!! note
@@ -42,7 +42,7 @@ to its documentation for more information about the search paths. Additionally,
support for config files written in YAML via the package [`yaml`](https://npm.im/yaml).
If a config file is found and successfully [validated](#validation), the result will be merged with
a set of defaults and any additional CLI arguments. CLI arguments have precedence over config
a set of defaults and any additionall CLI arguments. CLI arguments have precedence over config
files, and config files have precedence over defaults.
## Validation
@@ -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/bootstrap/config-file.js`), it will call the `validate` function exported
When a config file is found (`lib/config-file.js`), it will call the `validate` function exported
from `lib/schema/schema.js` with the contents of the config file. In turn, this asks `ajv` to
validate the data against the schema that Appium has provided it.
@@ -203,7 +203,7 @@ desired.
Any property defined in the schema having type `array` will _automatically_ uses the `csv`
transformer. Likewise, a property having type `object` will use the `json` transformer. It's
conceivable that `array` may want to use the `json` transformer, but otherwise, the presence of
the `appiumCliTransformer` keyword on an `array`-or-`object`-typed property is not strictly
the `appiumCliTransformer` keyword on an `array`-or-`object`-typed property is not stricly
necessary.
The adapter (remember the adapter?) creates a pipeline function including a special "CSV
@@ -250,7 +250,7 @@ An `ArgSpec` object stores the following metadata:
| `dest` | Property name in parsed arguments object (as returned by `argparse`'s `parse_args()`) |
| `defaultValue?` | Value of the `default` keyword in schema, if appropriate |
When a schema is [finalized](#schema-loading), the `Map` is populated with `ArgSpec` objects
When a schema is [finalized](#schema-finalization), the `Map` is populated with `ArgSpec` objects
for all known arguments.
So when the adapter is creating the pipeline of functions for the argument's `type`, it already has
@@ -323,7 +323,7 @@ One of the design goals of this system is the following:
_An extension should be able to register custom CLI arguments with the Appium, and a user should be
able to use them like any other argument_.
Previously, Appium accepted arguments in this manner (via `--driverArgs`), but validation was
Previously, Appium 2 accepted arguments in this manner (via `--driverArgs`), but validation was
hand-rolled and required extension implementors to use a custom API. It also required the user to
awkwardly pass a JSON string as the configuration on the command-line. Further, no contextual help
(via `--help`) existed for these arguments.
+2 -2
View File
@@ -2,10 +2,10 @@
hide:
- toc
title: Developing Appium Extensions
title: Intro to Development
---
Appium is built with a modular structure, which means that Appium extensions (drivers and plugins)
Appium 2 is built with a modular structure, which means that Appium extensions (drivers and plugins)
are decoupled from the main Appium module, and you only need to install the extensions that you
want to use. This modular structure also unlocks the ability to develop entirely new extensions!
@@ -1,49 +0,0 @@
---
hide:
- toc
title: Masking Sensitive Log Data
---
Since Appium server version 2.18.0 there is a possibility to mask sensitive
values in logs. The below tutorial explains how to use this feature in third-party
extensions.
## Why It Might Be Useful
It is the right call to hide sensitive information, like passwords, tokens, etc.
from server logs, so it does not accidentally leak if these logs end up in wrong hands.
Appium server already provides a way to manipulate logs records via
[filtering](../guides/log-filters.md), although it has its own limitations.
The current approach is more sophisticated though, and requires some fine-tuning
on the driver/plugin side.
## How To
The assumption is that your extension uses the standard built-in
[@appium/logger](https://www.npmjs.com/package/@appium/logger).
In order to get some value in logs replaced by a generic mask it is necessary:
- Change the logging expression to wrap sensitive values and format them, for example:
```js
this.log.info(`Value: ${value}`);
```
becomes
```js
import {logger} from '@appium/support';
this.log.info('Value: %s', logger.markSensitive(value));
```
The formatting happens via the standard Node.js's
[util.format](https://nodejs.org/api/util.html#utilformatformat-args) API.
- While sending the appropriate server request, where this log line is used and should be masked,
add the custom header `X-Appium-Is-Sensitive` with its value set to `1` or `true` (case-insensitive).
Without such header the above log value is not going to be masked.
This way it is possible to conditionally mask log records depending on which
request is being handled by the extension if the log expression is used in the
common section.
+23 -112
View File
@@ -1,4 +1,7 @@
---
hide:
- toc
title: Appium Clients
---
@@ -6,127 +9,35 @@ You need a client to write and run Appium scripts. You'll want to become very
familiar with your client documentation (as well as the documentation of any Selenium client that
the Appium client depends on) since that will be your primary interface to Appium.
To learn more about clients, check out the [Client Intro](../intro/clients.md).
To learn more about clients, read our [Client Intro](../intro/clients.md).
!!! note
If you maintain an Appium client that you would like to be listed here, feel free to create a PR!
## Official Clients
### Official Clients
These clients are currently maintained by the Appium team:
### [Java Client](https://github.com/appium/java-client)
|Client|Language|
|-|-|
|[Appium Java client](https://github.com/appium/java-client)|Java|
|[Appium Python client](https://github.com/appium/python-client)|Python|
|[Appium Ruby Core client](https://github.com/appium/ruby_lib_core) (Recommended)<br>[Appium Ruby client](https://github.com/appium/ruby_lib)|Ruby|
|[Appium .NET client](https://github.com/appium/dotnet-client)|C#|
Language: :fontawesome-brands-java: Java
### Other Clients
=== "Setup With Maven"
These clients are not maintained by the Appium team and can be used with other languages:
```xml
<dependency>
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>${version.you.require}</version>
<scope>test</scope>
</dependency>
```
=== "Setup With Gradle"
```groovy
dependencies {
testImplementation 'io.appium:java-client:${version.you.require}'
}
```
### [Python Client](https://github.com/appium/python-client)
Language: :fontawesome-brands-python: Python
```sh title="Install From PyPi"
pip install Appium-Python-Client
```
### [Ruby Core Client](https://github.com/appium/ruby_lib_core)
Language: :material-language-ruby: Ruby
```sh title="Install From RubyGems"
gem install appium_lib_core
```
### [Ruby Client](https://github.com/appium/ruby_lib)
Language: :material-language-ruby: Ruby
This client is a wrapper for the Ruby Core Client with several helper methods, though this may
add additional complexity, therefore the Ruby Core Client is recommended instead.
```sh title="Install From RubyGems"
gem install appium_lib
```
### [.NET Client](https://github.com/appium/dotnet-client)
Language: :simple-dotnet: C#
```sh title="Install Using .NET CLI"
dotnet add package Appium.WebDriver
```
## Other Clients
These clients are not maintained by the Appium team and can be used with other languages.
|Client|Language|
|-|-|
|[WebdriverIO](https://webdriver.io/docs/appium)|Node.js|
|[Nightwatch.js](https://nightwatchjs.org/guide/mobile-app-testing/introduction.html)|Node.js|
|[RobotFramework](https://github.com/serhatbolsu/robotframework-appiumlibrary)|DSL|
|[multicatch's appium-client](https://github.com/multicatch/appium-client)|Rust|
|[SwiftAppium](https://github.com/milcgroup/swiftappium)|Swift|
In general, any W3C WebDriver spec-compatible client will also integrate well with Appium, though
some Appium-specific commands may not be implemented in other clients.
### [WebdriverIO](https://webdriver.io/docs/appium)
!!! note
Language: :material-language-javascript: :material-language-typescript: JavaScript/TypeScript
```sh title="Setup Using npm"
npm init wdio@latest .
```
### [Nightwatch.js](https://nightwatchjs.org/guide/mobile-app-testing/introduction.html)
Language: :material-language-javascript: :material-language-typescript: JavaScript/TypeScript
=== "Setup For Android"
```sh
npx @nightwatch/mobile-helper android --appium
```
=== "Setup For iOS"
```sh
npx @nightwatch/mobile-helper ios --appium
```
### [RobotFramework AppiumLibrary](https://github.com/serhatbolsu/robotframework-appiumlibrary)
Language: :simple-robotframework: Robot Framework
```sh title="Install From PyPi"
pip install robotframework-appiumlibrary
```
### [multicatch's appium-client](https://github.com/multicatch/appium-client)
Language: :simple-rust: Rust
```sh title="Install Using Cargo"
cargo add appium-client
```
### [SwiftAppium](https://github.com/milcgroup/swiftappium)
Language: :material-language-swift: Swift
```sh title="Install and Setup"
git clone https://github.com/milcgroup/SwiftAppium.git
cd SwiftAppium
swift build
swift run swiftappium
```
If you maintain an Appium client that you would like to be listed in the Appium docs, feel free
to make a PR to add it to this section with a link to the documentation for the client.
+42 -207
View File
@@ -1,217 +1,52 @@
---
hide:
- toc
title: Appium Drivers
---
You can't use Appium without a driver! Here you can find a list of all known Appium drivers,
along with their installation commands and links to their documentation.
You can't use Appium without at least one driver! Click on the link for each driver to see the
specific installation instructions and documentation for that driver.
Generally, drivers can be installed using their listed installation key, with the following command:
```
appium driver install <installation key>
```
To learn more about drivers, check out the [Driver Intro](../intro/drivers.md).
!!! note
If you maintain an Appium driver that you would like to be listed here, feel free to create a PR!
## Official Drivers
### Official Drivers
These drivers are currently maintained by the Appium team:
### [Chromium](https://github.com/appium/appium-chromium-driver)
* Target: Desktop and mobile Chromium browsers (Chrome, Microsoft Edge, etc.)
* Mode: Web
```sh title="Install This Driver"
appium driver install chromium
```
### [Espresso](https://github.com/appium/appium-espresso-driver)
* Target: Android applications
* Mode: Native
```sh title="Install This Driver"
appium driver install espresso
```
### [Gecko](https://github.com/appium/appium-geckodriver)
* Target: Desktop and mobile Gecko browsers (Firefox)
* Mode: Web
```sh title="Install This Driver"
appium driver install gecko
```
### [Mac2](https://github.com/appium/appium-mac2-driver)
* Target: macOS applications
* Mode: Native
```sh title="Install This Driver"
appium driver install mac2
```
### [Safari](https://github.com/appium/appium-safari-driver)
* Target: Desktop and mobile Safari browsers
* Mode: Web
```sh title="Install This Driver"
appium driver install safari
```
### [UiAutomator2](https://github.com/appium/appium-uiautomator2-driver)
* Target: Android, Android TV, Android Wear applications
* Modes: Native, Hybrid, Web
```sh title="Install This Driver"
appium driver install uiautomator2
```
### [Windows](https://github.com/appium/appium-windows-driver)
!!! warning
Only the Node.js-based driver part is maintained by the Appium team. The server part
(WinAppDriver executable) is provided by Microsoft, but has not been maintained since 2022.
* Target: Windows applications
* Mode: Native
```sh title="Install This Driver"
appium driver install windows
```
### [XCUITest](https://appium.github.io/appium-xcuitest-driver/)
* Target: iOS, iPadOS, tvOS applications
* Modes: Native, Hybrid, Web
```sh title="Install This Driver"
appium driver install xcuitest
```
## Other Drivers
These drivers are not maintained by the Appium team and can be used to target other platforms:
### [Flutter](https://github.com/appium/appium-flutter-driver)
* Target: iOS and Android applications built with Flutter
* Mode: Native
* Supported by: Appium Team / Community
```sh title="Install This Driver"
appium driver install --source=npm appium-flutter-driver
```
### [Flutter Integration](https://github.com/AppiumTestDistribution/appium-flutter-integration-driver)
* Target: iOS and Android applications built with Flutter
* Mode: Native
* Supported by: Community / `@AppiumTestDistribution`
```sh title="Install This Driver"
appium driver install --source=npm appium-flutter-integration-driver
```
### [LG WebOS](https://github.com/headspinio/appium-lg-webos-driver)
* Target: LG TV web applications
* Mode: Web
* Supported by: HeadSpin
```sh title="Install This Driver"
appium driver install --source=npm appium-lg-webos-driver
```
### [Linux (@fantonglang)](https://github.com/fantonglang/appium-linux-driver)
!!! warning
This driver has not been maintained since 2022 and requires a custom Appium installation
* Target: Linux applications
* Mode: Native
* Supported by: `@fantonglang`
```sh title="Install This Driver"
git clone https://github.com/fantonglang/appium
cd appium
yarn install
node ./
```
### [Linux (@Itsmeaj)](https://github.com/Itsmeaj/appium)
* Target: Linux desktop applications on X11 and Wayland
* Mode: Native
* Supported by: `@Itsmeaj`
```sh title="Install This Driver"
appium driver install --source=npm @itsmeaj/appium-linux-driver
```
### [NovaWindows](https://github.com/AutomateThePlanet/appium-novawindows-driver)
!!! info
This driver is recommended as a drop-in replacement for the partially unmaintained
[Windows driver](#windows)
* Target: Windows applications
* Mode: Native
* Supported by: Community / Automate The Planet
```sh title="Install This Driver"
appium driver install --source=npm appium-novawindows-driver
```
### [Roku](https://github.com/headspinio/appium-roku-driver)
* Target: Roku channels (applications)
* Mode: Native
* Supported by: HeadSpin
```sh title="Install This Driver"
appium driver install --source=npm @headspinio/appium-roku-driver
```
### [Tizen](https://github.com/Samsung/appium-tizen-driver)
!!! warning
This driver has not been maintained since 2020 and is only compatible with Appium 1
* Target: Tizen applications
* Mode: Native
* Supported by: Community / Samsung
```sh title="Install This Driver"
npm install appium-tizen-driver
```
### [TizenTV](https://github.com/headspinio/appium-tizen-tv-driver)
* Target: Tizen TV web applications
* Mode: Web
* Supported by: HeadSpin
```sh title="Install This Driver"
appium driver install --source=npm appium-tizen-tv-driver
```
### [You.i Engine](https://github.com/YOU-i-Labs/appium-youiengine-driver)
!!! warning
This driver has not been maintained since 2022 and is only compatible with Appium 1
* Target: iOS, Android, macOS, Linux, tvOS applications built with You.i Engine
* Mode: Native
* Supported by: Community / You.i
```sh title="Install This Driver"
npm install appium-youiengine-driver
```
|Driver|Installation Key|Platform(s)|Mode(s)|
|--|--|--|--|
|[Chromium](https://github.com/appium/appium-chromium-driver)|`chromium`|macOS, Windows, Linux|Web|
|[Espresso](https://github.com/appium/appium-espresso-driver)|`espresso`|Android|Native|
|[Gecko](https://github.com/appium/appium-geckodriver)|`gecko`|macOS, Windows, Linux, Android|Web|
|[Mac2](https://github.com/appium/appium-mac2-driver)|`mac2`|macOS|Native|
|[Safari](https://github.com/appium/appium-safari-driver)|`safari`|macOS, iOS|Web|
|[UiAutomator2](https://github.com/appium/appium-uiautomator2-driver)|`uiautomator2`|Android|Native, Hybrid, Web|
|[Windows](https://github.com/appium/appium-windows-driver)|`windows`|Windows|Native|
|[XCUITest](https://github.com/appium/appium-xcuitest-driver)|`xcuitest`|iOS|Native, Hybrid, Web|
### Other Drivers
These drivers are not maintained by the Appium team and can be used to target additional platforms:
|Driver|Installation Key|Platform(s)|Mode(s)|Supported By|
|--|--|--|--|--|
|[Flutter](https://github.com/appium/appium-flutter-driver)|`--source=npm appium-flutter-driver`|iOS, Android|Native|Community|
|[Flutter Integration](https://github.com/AppiumTestDistribution/appium-flutter-integration-driver)|`--source=npm appium-flutter-integration-driver`|iOS, Android|Native|Community / `@AppiumTestDistribution`|
|[LG WebOS](https://github.com/headspinio/appium-lg-webos-driver)|`--source=npm appium-lg-webos-driver`|LG TV|Web|HeadSpin|
|[Linux](https://github.com/fantonglang/appium-linux-driver)|`--source=npm @stdspa/appium-linux-driver`|Linux|Native|`@fantonglang`|
|[Roku](https://github.com/headspinio/appium-roku-driver)|`--source=npm @headspinio/appium-roku-driver`|Roku|Native|HeadSpin|
|[Tizen](https://github.com/Samsung/appium-tizen-driver)|`--source=npm appium-tizen-driver`|Android|Native|Community / Samsung|
|[TizenTV](https://github.com/headspinio/appium-tizen-tv-driver)|`--source=npm appium-tizen-tv-driver`|Samsung TV|Web|HeadSpin|
|[Youi](https://github.com/YOU-i-Labs/appium-youiengine-driver)|`--source=npm appium-youiengine-driver`|iOS, Android, macOS, Linux, tvOS|Native|Community / You.i|
|[NovaWindows](https://github.com/AutomateThePlanet/appium-novawindows-driver)|`--source=npm appium-novawindows-driver`|Windows|Native|Community / Automate The Planet|
!!! note
If you maintain an Appium driver that you would like to be listed in the Appium docs, feel free
to make a PR to add it to this section with a link to the driver documentation.
+1 -1
View File
@@ -2,7 +2,7 @@
hide:
- toc
title: The Appium Ecosystem
title: Ecosystem Overview
---
Appium has a wide ecosystem of related software and tools. This section of the Appium documentation
+28 -120
View File
@@ -1,4 +1,7 @@
---
hide:
- toc
title: Appium Plugins
---
@@ -6,133 +9,38 @@ Plugins offer various ways to extend or modify Appium's behaviour. They are _com
and are not needed for standard automation functionality, but you may find them to be useful
for more specialised automation workflows.
!!! note
Generally, plugins can be installed using their listed installation key, with the following command:
```
appium plugin install <installation key>
```
If you maintain an Appium plugin that you would like to be listed here, feel free to create a PR!
## Official Plugins
### Official Plugins
These plugins are are currently maintained by the Appium team:
### [Execute Driver](https://github.com/appium/appium/tree/master/packages/execute-driver-plugin)
|<div style="width:7em">Plugin</div>|<div style="width:8em">Installation Key</div>|Description|
|---|---|---|
|[Execute Driver](https://github.com/appium/appium/tree/master/packages/execute-driver-plugin)|`execute-driver`|Run entire batches of commands in a single call to the Appium server|
|[Images](https://github.com/appium/appium/tree/master/packages/images-plugin)|`images`|Image matching and comparison features|
|[Relaxed Caps](https://github.com/appium/appium/tree/master/packages/relaxed-caps-plugin)|`relaxed-caps`|Relax Appium's requirement for vendor prefixes on capabilities|
|[Storage](https://github.com/appium/appium/tree/master/packages/storage-plugin)|`storage`|Server-side storage with client-side management|
|[Universal XML](https://github.com/appium/appium/tree/master/packages/universal-xml-plugin)|`universal-xml`|Instead of the standard XML format for iOS and Android, use an XML definition that is the same across both platforms|
Run entire batches of commands in a single call to the Appium server
```sh title="Install This Plugin"
appium plugin install execute-driver
```
### [Images](https://github.com/appium/appium/tree/master/packages/images-plugin)
Add support for image matching and comparison features
```sh title="Install This Plugin"
appium plugin install images
```
### [Inspector](https://github.com/appium/appium-inspector/tree/main/plugins)
Integrate the [Appium Inspector](https://appium.github.io/appium-inspector/) directly into your
Appium server installation
```sh title="Install This Plugin"
appium plugin install inspector
```
### [Relaxed Caps](https://github.com/appium/appium/tree/master/packages/relaxed-caps-plugin)
Relax Appium's requirement for vendor prefixes on capabilities
```sh title="Install This Plugin"
appium plugin install relaxed-caps
```
### [Storage](https://github.com/appium/appium/tree/master/packages/storage-plugin)
Add server-side storage with client-side management
```sh title="Install This Plugin"
appium plugin install storage
```
### [Universal XML](https://github.com/appium/appium/tree/master/packages/universal-xml-plugin)
Translate the default iOS and Android XML formats into a common format
```sh title="Install This Plugin"
appium plugin install universal-xml
```
## Other Plugins
### Other Plugins
These plugins are not maintained by the Appium team and can provide additional functionality:
### [AltUnity](https://github.com/headspinio/appium-altunity-plugin)
|<div style="width:6em">Plugin</div>|<div style="width:19em">Installation Key</div>|Description|<div style="width:13em">Supported By</div>|
|---|---|---|---|
|[AltUnity](https://github.com/headspinio/appium-altunity-plugin)|`--source=npm appium-altunity-plugin`|Target Unity games and apps for automation with a new context, via the AltUnityTester framework|HeadSpin|
|[Device Farm](https://github.com/AppiumTestDistribution/appium-device-farm)|`--source=npm appium-device-farm`|Manage and create driver sessions on connected Android devices and iOS simulators|`@AppiumTestDistribution`|
|[Gestures](https://github.com/AppiumTestDistribution/appium-gestures-plugin)|`--source=npm appium-gestures-plugin`|Perform basic gestures using W3C Actions|`@AppiumTestDistribution`|
|[Interceptor](https://github.com/AppiumTestDistribution/appium-interceptor-plugin)|`--source=npm appium-interceptor`|Intercept and mock API requests and responses|`@AppiumTestDistribution`|
|[OCR](https://github.com/jlipps/appium-ocr-plugin)|`--source=npm appium-ocr-plugin`|Find elements via OCR text|`@jlipps`|
|[Reporter](https://github.com/AppiumTestDistribution/appium-reporter-plugin)|`--source=npm appium-reporter-plugin`|Generate standalone consolidated HTML reports with screenshots|`@AppiumTestDistribution`|
|[Wait](https://github.com/AppiumTestDistribution/appium-wait-plugin)|`--source=npm appium-wait-plugin`|Manage global element wait timeouts|`@AppiumTestDistribution`|
Target Unity games and apps for automation via the AltUnityTester framework
!!! note
Supported by: HeadSpin
```sh title="Install This Plugin"
appium plugin install --source=npm appium-altunity-plugin
```
### [Device Farm](https://github.com/AppiumTestDistribution/appium-device-farm)
Manage and create driver sessions on connected Android devices and iOS simulators
Supported by: `@AppiumTestDistribution`
```sh title="Install This Plugin"
appium plugin install --source=npm appium-device-farm
```
### [Gestures](https://github.com/AppiumTestDistribution/appium-gestures-plugin)
Perform basic gestures using W3C Actions
Supported by: `@AppiumTestDistribution`
```sh title="Install This Plugin"
appium plugin install --source=npm appium-gestures-plugin
```
### [Interceptor](https://github.com/AppiumTestDistribution/appium-interceptor-plugin)
Intercept and mock API requests and responses
Supported by: `@AppiumTestDistribution`
```sh title="Install This Plugin"
appium plugin install --source=npm appium-interceptor
```
### [OCR](https://github.com/jlipps/appium-ocr-plugin)
Find elements via OCR text
Supported by: `@jlipps`
```sh title="Install This Plugin"
appium plugin install --source=npm appium-ocr-plugin
```
### [Reporter](https://github.com/AppiumTestDistribution/appium-reporter-plugin)
Generate standalone consolidated HTML reports with screenshots
Supported by: `@AppiumTestDistribution`
```sh title="Install This Plugin"
appium plugin install --source=npm appium-reporter-plugin
```
### [Wait](https://github.com/AppiumTestDistribution/appium-wait-plugin)
Manage global element wait timeouts
Supported by: `@AppiumTestDistribution`
```sh title="Install This Plugin"
appium plugin install --source=npm appium-wait-plugin
```
If you maintain an Appium plugin that you would like to be listed in the Appium docs, feel free
to make a PR to add it to this section with a link to the documentation for the plugin.
+24 -88
View File
@@ -1,106 +1,42 @@
---
hide:
- toc
title: Appium-Related Tools
---
The Appium ecosystem also includes several tools that have been created to assist with things not
directly related to running tests, such as Appium installation, test development, and more.
There are several Appium tools that have been created to to assist with things not directly related
to testing, such as Appium installation, test development, and more.
!!! note
If you maintain an Appium tool that you would like to be listed here, feel free to create a PR!
## Official Tools
These tools are currently maintained by the Appium team:
### [Appium Inspector](https://appium.github.io/appium-inspector/)
### [Appium Inspector](https://appium.github.io/appium-inspector/latest/)
Appium has a graphical client which can be used to inspect application screenshots, view the
application hierarchy, search for elements, run Appium commands, record app interactions, and more.
It can be very useful for Appium test development.
application hierarchy, run Appium commands, record app interactions, and more. It is 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:
Find downloads and more information on its GitHub page: [Appium Inspector](https://github.com/appium/appium-inspector)
### Appium Doctor
The Appium Doctor tool can be used to validate whether all prerequisites and other environment
details needed for the driver/plugin have been set up correctly. The tool can be accessed via the
[`doctor` command in the Appium CLI](../reference/cli/extensions.md#doctor):
Appium Doctor is a command-line tool built into Appium drivers and plugins.
The command is expected to be used to validate whether a driver or plugin has all of its prerequisites and other environment details set up correctly
if the driver/plugin author implemented the `doctor` command.
```sh
appium {driver|plugin} doctor <extension-name>
For example, `uiautomator2` driver provides the `doctor` command below.
```
appium driver doctor uiautomator2
```
It shows no results if the driver/plugin does not have such validation checks.
It shows no result if the driver/plugin author did not implement them.
!!! note
More information on this command can be found in the [Command-Line Usage documentation](../cli/extensions.md#doctor).
For driver/plugin developers, please read [Building Doctor Checks](../developing/build-doctor-checks.md).
If you maintain an Appium extension and would like to add Appium Doctor support for it, check
out the documentation on [Building Doctor Checks](../developing/build-doctor-checks.md).
### Other Tools
## Other Tools
These tools are not maintained by the Appium team and can be used to assist with other problems:
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.
It includes commands for installing Appium, its drivers and plugins, as well as validating
prerequisites for iOS or Android emulators or real devices.
Supported by: `@AppiumTestDistribution`
```sh title="Install This Tool"
npm install -g appium-installer
```
|Name|Description|Supported By|
|---|---|---|
|[appium-installer](https://github.com/AppiumTestDistribution/appium-installer)|Help set up an Appium environment for Android and iOS|`@AppiumTestDistribution`|
+3 -3
View File
@@ -56,15 +56,15 @@ on per-process basis, so each test session initialized in scope of the same Appi
of it. It is a [LRU Cache](https://www.npmjs.com/package/lru-cache) with the following limitations:
- Max items: 1024. You may customize it by providing a new value to
the [APPIUM_APPS_CACHE_MAX_ITEMS](../reference/cli/env-vars.md) environment variable.
the [APPIUM_APPS_CACHE_MAX_ITEMS](../cli/env-vars.md) environment variable.
Do not set it to a lower number than the amount of apps in all parallel sessions per process.
- Max time to live (TTL) for each entry: 24 hours.
You may customize it by providing a new value to the
[APPIUM_APPS_CACHE_MAX_AGE](../reference/cli/env-vars.md) environment variable.
[APPIUM_APPS_CACHE_MAX_AGE](../cli/env-vars.md) environment variable.
Do not set it to a lower number than the duration of a single session startup.
- TTL is refreshed for each entry upon access
- By default the full application URL is used as cache key. You may change this behavior
by enabling the [APPIUM_APPS_CACHE_IGNORE_URL_QUERY](../reference/cli/env-vars.md) environment variable.
by enabling the [APPIUM_APPS_CACHE_IGNORE_URL_QUERY](../cli/env-vars.md) environment variable.
If the above option is enabled then the 'search' part of the app URL will be cut off from cache keys.
See the corresponding [feature request](https://discuss.appium.io/t/regarding-app-caching-when-using-aws-s3-presigned-urls/42713)
for more details.
+55 -51
View File
@@ -2,14 +2,14 @@
title: Session Capabilities
---
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.
"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.
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:
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:
| Capability Name | Type | Description |
|------------------|----------|------------------------------------------------|
@@ -17,62 +17,65 @@ The WebDriver spec defines a small set of standard capabilities, including the f
| `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
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 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.
Here are a few commonly (but not universally!) used Appium-specific capabilities:
Here is a list of all the globally-recognized Appium capabilities:
| 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 |
!!! info
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.
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
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.
| <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`) |
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.
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.
!!! note
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.
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.
## BiDi Protocol Support
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.
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.
| 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.
| Capability Name | Type | Description |
|-----------------|-----------|-----------------------------------------|
| `webSocketUrl` | `boolean` | To enable BiDi protocol in the session. |
## Using `appium:options` to Group Capabilities
@@ -115,7 +118,8 @@ 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) for
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
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.
@@ -140,7 +144,7 @@ drivers and plugins. It is of course up to each service provider how they wish t
discovery, installation, and availability of any official or third party drivers or plugins. But
the Appium team does provide several suggestions, for consistency across the industry. _These are
recommendations only,_ and not a standard, but adopting it will help users to navigate the increased
complexity that working with Appium in a cloud environment may bring.
complexity that working with Appium 2 in a cloud environment may bring.
### Suggested capabilities
+15 -8
View File
@@ -6,12 +6,14 @@ title: Retrieving Event Timings
---
Appium comes with the ability to retrieve timing information about startup
information and command length. This is an advanced feature; event and
command timings are collected automatically for the duration of a session.
information and command length. This is an advanced feature that is controlled
by the use of the `appium:eventTimings` capability (set it to `true` to log event
timings).
The `POST /session/:id/appium/events` response (i.e., the response to
`driver.logs.events` or similar, depending on client) has the following
structure:
With this capability turned on, the `POST /session/:id/appium/events` response (i.e.,
the response to `driver.logs.events` or similar, depending on client) will be
decorated with an `events` property. This is the structure of that `events`
property:
```
{
@@ -65,7 +67,12 @@ generate various kinds of reports from event timings output:
## Add a custom event
!!! warning "TODO"
The links to the commands in the following paragraph do not yet work since these docs are under
construction.
You can add custom events that will show up in the event timings data. You can send a custom event
name to the Appium server using the [Log Custom Event API](../reference/api/appium.md#logcustomevent),
and the server will store the timestamp. The [Get Log Events](../reference/api/appium.md#getlogevents)
command can be used to retrieve named events' timestamps later on.
name to the Appium server using the [Log Event API](#TODO), and the server will store the
timestamp. The [Get Events](#TODO) command can be used to retrieve named events' timestamps later
on.
+67 -20
View File
@@ -22,11 +22,9 @@ server:
use-drivers:
- xcuitest
default-capabilities:
appium:wdaLocalPort: 8100
appium:mjpegServerPort: 9100
appium:mjpegScreenshotUrl: "http://localhost:9100"
appium:platformVersion: "26.0"
appium:deviceName: "iPhone 17"
wdaLocalPort: 8100
mjpegServerPort: 9100
mjpegScreenshotUrl: "http://localhost:9100"
```
In the above YAML config file, we specify the Appium server port, the driver used, and parameters
@@ -41,11 +39,9 @@ server:
use-drivers:
- xcuitest
default-capabilities:
appium:wdaLocalPort: 8110
appium:mjpegServerPort: 9110
appium:mjpegScreenshotUrl: "http://localhost:9110"
appium:platformVersion: "26.0"
appium:deviceName: "iPhone 16"
wdaLocalPort: 8110
mjpegServerPort: 9110
mjpegScreenshotUrl: "http://localhost:9110"
```
### Define the Grid node configs
@@ -64,15 +60,11 @@ port = 5555
[node]
detect-drivers = false
[events]
publish = "tcp://HUB_IP_ADDRESS:4442"
subscribe = "tcp://HUB_IP_ADDRESS:4443"
[relay]
url = "http://localhost:4723"
status-endpoint = "/status"
configs = [
"1", "{\"platformName\": \"iOS\", \"appium:automationName\": \"XCUITest\"}"
"1", "{\"platformName\": \"iOS\", \"appium:platformVersion\": \"15.5\", \"appium:deviceName\": \"iPhone 13\", \"appium:automationName\": \"XCUITest\"}"
]
```
@@ -84,15 +76,11 @@ port = 5565
[node]
detect-drivers = false
[events]
publish = "tcp://HUB_IP_ADDRESS:4442"
subscribe = "tcp://HUB_IP_ADDRESS:4443"
[relay]
url = "http://localhost:4733"
status-endpoint = "/status"
configs = [
"1", "{\"platformName\": \"iOS\", \"appium:automationName\": \"XCUITest\"}"
"1", "{\"platformName\": \"iOS\", \"appium:platformVersion\": \"15.5\", \"appium:deviceName\": \"iPhone 12\", \"appium:automationName\": \"XCUITest\"}"
]
```
@@ -117,3 +105,62 @@ hub, you'll be able to send all your Appium traffic via the single hub endpoint
And of course, you're able to link up Appium servers and nodes running on different machines in
your network to form a larger grid.
## Using Selenium Grid 3
It is possible to register your Appium server with a local [Selenium Grid 3](https://www.selenium.dev/documentation/legacy/selenium_3/grid_3/)
([setup docs](https://www.selenium.dev/documentation/legacy/grid_3/setting_up_your_own_grid/)) instance by using the
`--nodeconfig` server argument.
```bash
appium server --nodeconfig /path/to/nodeconfig.json --base-path=/wd/hub
```
In the referenced config file you have to define the `browserName`, `version` and `platform`
capabilities and based on these parameters the grid will re-direct your test to the right device.
You will also need to configure your host details and the Selenium Grid details. For a full list of
all parameters and descriptions see
[here](https://www.selenium.dev/documentation/legacy/selenium_3/grid_setup/).
Once you start the Appium server it will register with the grid, and you will see your device on
the grid console page:
`http://**\<grid-ip-adress\>**:**\<grid-port\>**/grid/console`
### Example Grid Node Configuration JSON
```json
{
"capabilities":
[
{
"browserName": "<e.g._iPhone5_or_iPad4>",
"version":"<version_of_iOS_e.g._7.1>",
"maxInstances": 1,
"platform":"<platform_e.g._MAC_or_ANDROID>"
}
],
"configuration":
{
"cleanUpCycle":2000,
"timeout":30000,
"proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
"url":"http://<host_name_appium_server_or_ip-address_appium_server>:<appium_port>/wd/hub",
"host": "<host_name_appium_server_or_ip-address_appium_server>",
"port": <appium_port>,
"maxSession": 1,
"register": true,
"registerCycle": 5000,
"hubPort": <grid_port>,
"hubHost": "<Grid_host_name_or_grid_ip-address>",
"hubProtocol": "<Protocol_of_Grid_defaults_to_http>"
}
}
```
If `url`, `host`, and `port` are not given, the config will be auto updated to point to
`localhost:<appium-port>`.
If your Appium server is running on a different machine to your Selenium Grid server, make sure you
use an external name/IP address in your `host` and `url` configuration; `localhost` and `127.0.0.1`
will prevent Selenium Grid from connecting correctly.
@@ -16,7 +16,7 @@ two basic strategies: using Appium's extension CLI interface, or managing extens
## Using Appium's Extension CLI
With Appium's [Extension CLI](../reference/cli/extensions.md), you let Appium manage drivers and plugins for
With Appium's [Extension CLI](../cli/extensions.md), you let Appium manage drivers and plugins for
you. You will use CLI commands to tell Appium which extensions you would like to install, update,
or remove. Here's an example of how you might install a driver using the CLI:
@@ -31,11 +31,15 @@ installing it only installs the core Appium server, without any drivers.
When it comes to installing Appium 2 drivers, there are several approaches you can take:
* Use the [Appium Extension CLI](../reference/cli/extensions.md), for example:
* Add the `--drivers` flag when installing Appium, for example:
```bash
npm i -g appium --drivers=xcuitest,uiautomator2
```
* Use the [Appium Extension CLI](../cli/extensions.md), for example:
```bash
appium driver install uiautomator2
```
* Use the [Appium Setup CLI command](../reference/cli/setup.md) (added in Appium `2.6`), for example:
* Use the [Appium Setup CLI command](../cli/setup.md) (added in Appium `2.6`), for example:
```bash
appium setup mobile
```
@@ -69,7 +73,7 @@ server and drivers are separate packages, they can release new versions independ
other - this means that you no longer need to wait for a new Appium server release, but can install
the latest driver versions right away.
Checking for driver updates is done by using the [Appium Extension CLI](../reference/cli/extensions.md):
Checking for driver updates is done by using the [Appium Extension CLI](../cli/extensions.md):
```bash
appium driver list --updates
@@ -92,7 +96,7 @@ server package.
!!! info "Actions Needed"
Make sure to use the [Appium Extension CLI](../reference/cli/extensions.md) to manage your drivers
Make sure to use the [Appium Extension CLI](../cli/extensions.md) to manage your drivers
### Deprecated Packages No Longer Supported
@@ -121,7 +125,7 @@ path to `/`, therefore the default server URL is now `http://localhost:4723/`.
In your test scripts, change the base path of the target server URL from `/wd/hub` to `/`.
Alternatively, you can retain the Appium 1 base path by launching Appium with the
`--base-path=/wd/hub` [command-line argument](../reference/cli/server.md).
`--base-path=/wd/hub` [command-line argument](../cli/args.md).
### Server Port 0 No Longer Supported
@@ -153,7 +157,8 @@ appium --driver-xcuitest-webdriveragent-port=5000 # Appium 2
appium --chromedriver-version=100 # Appium 1
CHROMEDRIVER_VERSION=100 appium # Appium 2
```
* Some options can now be passed as [capabilities](./caps.md), for example:
* Some options can now be passed as [capabilities](https://appium.io/docs/en/latest/guides/caps/),
for example:
```
appium --chromedriver-executable=/path/to/chromedriver # Appium 1
{"appium:chromedriverExecutable": "/path/to/chromedriver"} # Appium 2
@@ -340,7 +345,7 @@ wish to take advantage of with Appium 2:
You are no longer limited to official drivers or plugins, or ones that the Appium team even knows
about! Developers can now create their own custom drivers or plugins, which can be installed via
Appium's [Extension CLI](../reference/cli/extensions.md) from `npm`, `git`, GitHub, or even the local
Appium's [Extension CLI](../cli/extensions.md) from `npm`, `git`, GitHub, or even the local
filesystem. Interested in building a driver or plugin? Check out the
[Building Drivers](../developing/build-drivers.md) and
[Building Plugins](../developing/build-plugins.md) guides.
@@ -1,464 +0,0 @@
---
title: Migrating to Appium 3
---
<style>
.md-typeset .grid {
grid-template-columns: repeat(auto-fit,minmax(min(100%,11rem),1fr));
}
</style>
This document is a guide for those who are using Appium 2 and would like to upgrade to Appium 3.
It contains a list of breaking changes, as well as suggestions for handling them.
While Appium 2 was a major overhaul of the entire Appium architecture, Appium 3 is a smaller
upgrade with fewer breaking changes, which should result in a much simpler migration process.
## Installation
The installation method for Appium 3 remains the same as for Appium 2. If you want to upgrade, you
can simply install Appium 3 on top of your existing installation:
```bash
# optional: `appium setup reset`
npm install -g appium
```
## Breaking Changes
### Node 20+ Required
With Appium 2, the minimum required Node version was `14.17.0`. Support for Node 14 had already
ended before the release of Appium 2, which meant that even users on outdated Node versions were
able to use it.
Appium 3 drops support for outdated Node versions, and bumps the minimum required version to Node
`20.19.0` (with the semver range `^20.19.0 || ^22.12.0 || >=24.0.0`), as well as the minimum `npm`
version to `10`.
!!! info "Actions Needed"
Upgrade Node.js to `v20.19.0` or newer, and `npm` to `v10` or newer
### Deprecated Endpoints Removed
Appium 3 removes many previously deprecated server endpoints. Some of these endpoints have now
become specific to one or more drivers, while most others have direct or close-to-direct
replacements in other endpoints. All removed endpoints, along with replacements (where applicable)
are listed [in the **Removed Endpoints** section](#removed).
Some W3C endpoints used in Appium also existed in the old JSONWP standard, but required different
parameters. With Appium 2, both standards for these endpoints were supported. Appium 3 changes
these endpoints by removing support for the JSONWP parameters, and only accepting the W3C
parameters. These endpoints are listed [in the **Modified Endpoints** section](#modified).
!!! info "Actions Needed"
Check your Appium client documentation for the affected methods, and adjust your code to use
their replacements
### Feature Flag Prefix Required
With Appium 2, it was possible to opt into certain [insecure features](./security.md) on server
startup, which could be enabled using the `--allow-insecure` or `--relaxed-security` flags. Appium
`2.13` added the ability to optionally provide a scope prefix to specific features, ensuring that
they would only be enabled for the specified driver (or all of them).
Appium 3 makes the scope prefix mandatory, and will throw an error if features are specified
without a scope. Note that the behavior of the `--relaxed-security` flag remains unchanged.
!!! info "Actions Needed"
If you use the `--allow-insecure` server flag, add a scope prefix before each feature name.
For example, if you use the UiAutomator2 `adb_shell` feature, on Appium 2 you would enable it
like this:
```
appium --allow-insecure=adb_shell
```
On Appium 3, to ensure this feature is only activated for UiAutomator2, you can run it like so:
```
appium --allow-insecure=uiautomator2:adb_shell
```
Alternatively, if you wish to keep the Appium 2 behavior and enable the feature for _all_
drivers that support it, you can use the wildcard (`*`) prefix:
```
appium --allow-insecure=*:adb_shell
```
Server-scope features like `session_discovery` also require the wildcard prefix.
### Session Discovery Requires Feature Flag
In Appium 2, it was possible to retrieve all active server sessions via the `GET /sessions`
endpoint. This information could then be used, for example, in Appium Inspector, in order to attach
to an existing session, instead of creating a new one.
Appium 3 makes two changes to the session discovery process:
* The `GET /sessions` endpoint is replaced with `GET /appium/sessions` (see [the Removed Endpoints section](#removed))
* The use of the new endpoint requires the `session_discovery` [feature flag](./security.md)
The return value of `GET /appium/sessions` is largely identical to `GET /sessions`, but additionally
includes the `created` field for each session entry, indicating the session creation time as a Unix
timestamp. The rest of the result format remains unchanged.
To reduce migration efforts, the `GET /appium/sessions` endpoint (locked behind the aforementioned
feature flag) is also available in Appium `2.19`, allowing you to adjust your code before upgrading
to Appium 3. As for Appium Inspector, support for this new endpoint is available starting from
version `2025.3.1`.
!!! info "Actions Needed"
* If your code uses session retrieval, change the endpoint from `GET /sessions` to
`GET /appium/sessions`
* If you use Appium Inspector's Attach to Session feature, upgrade to version `2025.3.1` or later
* In both cases, ensure your Appium server is launched with the `session_discovery`
[feature flag](./security.md)
### Unzip Logic Removed
Appium 3 removes the custom unzip logic used when working with files like application packages.
Such files are often only relevant to particular platforms, therefore the functionality for
handling these operations has been moved to relevant drivers.
!!! info "Actions Needed"
Ensure you are using the most recent versions of your drivers
### Express 5
Appium 3 upgrades the internally-used `express` dependency from `v4` to `v5`. This should not
affect users who use Appium directly, but developers integrating parts of Appium into their own
projects may want to check [the Express 5 Migration Guide](https://expressjs.com/en/guide/migrating-5.html).
!!! info "Actions Needed"
None! (hopefully)
## Endpoint Changes
### Removed
The following is a list of all the Appium server endpoints removed in Appium 3. For ease of
migration, additional information is provided for each endpoint: drivers that still support the
endpoint; suggested replacement endpoints, or, rarely, the lack of any available replacements.
Icons are used to indicate endpoint support in either certain drivers, or in the core Appium server
(applicable to all drivers):
<div class="grid cards" markdown>
- :simple-appium:{ .lg } - Appium server
- :material-apple:{ .lg } - [XCUITest driver](https://appium.github.io/appium-xcuitest-driver/latest/)
- :material-android:{ .lg } - [UiAutomator2 driver](https://github.com/appium/appium-uiautomator2-driver/)
- :material-coffee:{ .lg } - [Espresso driver](https://github.com/appium/appium-espresso-driver)
- :material-apple-finder:{ .lg } - [Mac2 driver](https://github.com/appium/appium-mac2-driver)
- :material-microsoft-windows:{ .lg } - [Windows driver](https://github.com/appium/appium-windows-driver)
</div>
* `GET /sessions`
* :octicons-arrow-right-24: `GET /appium/sessions` :simple-appium:
* `POST /session/:sessionId/accept_alert`
* :octicons-arrow-right-24: `POST /session/:sessionId/alert/accept` :simple-appium:
* :octicons-arrow-right-24: `mobile: alert` [execute method](./execute-methods.md) :material-apple:
* :octicons-arrow-right-24: `mobile: acceptAlert` execute method :material-android:
* `GET /session/:sessionId/alert_text`
* :octicons-arrow-right-24: `GET /session/:sessionId/alert/text` :simple-appium:
* `POST /session/:sessionId/alert_text`
* :octicons-arrow-right-24: `POST /session/:sessionId/alert/text` :simple-appium:
* `POST /session/:sessionId/appium/app/background`
* :octicons-arrow-right-24: `mobile: backgroundApp` execute method :material-apple: :material-android: :material-coffee:
* `POST /session/:sessionId/appium/app/close`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: `mobile: terminateApp` execute method :material-apple: :material-android: :material-coffee:
* :octicons-arrow-right-24: `macos: terminateApp` execute method :material-apple-finder:
* :octicons-arrow-right-24: `windows: closeApp` execute method :material-microsoft-windows:
* `POST /session/:sessionId/appium/app/end_test_coverage`
* :octicons-arrow-right-24: `mobile: shell` execute method :material-android: :material-coffee:
* `POST /session/:sessionId/appium/app/launch`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: `mobile: launchApp` execute method :material-apple:
* :octicons-arrow-right-24: `mobile: activateApp` or `mobile: startActivity` execute methods :material-android: :material-coffee:
* :octicons-arrow-right-24: `macos: launchApp` or `macos: activateApp` execute methods :material-apple-finder:
* :octicons-arrow-right-24: `windows: launchApp` execute method :material-microsoft-windows:
* `POST /session/:sessionId/appium/app/reset`
* :octicons-arrow-right-24: `mobile: clearApp` execute method :material-apple: [^sim] :material-android: :material-coffee:
* `POST /session/:sessionId/appium/app/strings`
* :octicons-arrow-right-24: `mobile: getAppStrings` execute method :material-apple: :material-android: :material-coffee:
* `GET /session/:sessionId/appium/device/app_state`
* :octicons-arrow-right-24: `POST /session/:sessionId/appium/device/app_state` :simple-appium:
* :octicons-arrow-right-24: `mobile: queryAppState` execute method :material-apple: :material-android: :material-coffee:
* :octicons-arrow-right-24: `macos: queryAppState` execute method :material-apple-finder:
* `GET /session/:sessionId/appium/device/current_activity`
* :octicons-arrow-right-24: `mobile: getCurrentActivity` execute method :material-android: :material-coffee:
* `GET /session/:sessionId/appium/device/current_package`
* :octicons-arrow-right-24: `mobile: getCurrentPackage` execute method :material-android: :material-coffee:
* `GET /session/:sessionId/appium/device/display_density`
* :octicons-arrow-right-24: `mobile: getDisplayDensity` execute method :material-android: :material-coffee:
* `POST /session/:sessionId/appium/device/finger_print`
* :octicons-arrow-right-24: `mobile: fingerPrint` execute method :material-android: [^sim] :material-coffee: [^sim]
* `POST /session/:sessionId/appium/device/get_clipboard`
* :octicons-check-24: Moved to drivers: :material-android: :material-coffee:
* :octicons-arrow-right-24: `mobile: getClipboard` execute method :material-apple: :material-android: :material-coffee:
* :octicons-arrow-right-24: `mobile: getPasteboard` execute method :material-apple: [^sim]
* :octicons-arrow-right-24: `windows: getClipboard` execute method :material-microsoft-windows:
* `POST /session/:sessionId/appium/device/gsm_call`
* :octicons-arrow-right-24: `mobile: gsmCall` execute method :material-android: [^sim] :material-coffee: [^sim]
* `POST /session/:sessionId/appium/device/gsm_signal`
* :octicons-arrow-right-24: `mobile: gsmSignal` execute method :material-android: [^sim] :material-coffee: [^sim]
* `POST /session/:sessionId/appium/device/gsm_voice`
* :octicons-arrow-right-24: `mobile: gsmVoice` execute method :material-android: [^sim] :material-coffee: [^sim]
* `POST /session/:sessionId/appium/device/is_locked`
* :octicons-arrow-right-24: `mobile: isLocked` execute method :material-apple: :material-android: :material-coffee:
* `POST /session/:sessionId/appium/device/keyevent`
* :octicons-arrow-right-24: `mobile: keys` execute method :material-apple: (iPadOS only)
* :octicons-arrow-right-24: `mobile: pressKey` execute method :material-android: :material-coffee:
* :octicons-arrow-right-24: `macos: keys` execute method :material-apple-finder:
* :octicons-arrow-right-24: `windows: keys` execute method :material-microsoft-windows:
* `POST /session/:sessionId/appium/device/lock`
* :octicons-arrow-right-24: `mobile: lock` execute method :material-apple: :material-android: :material-coffee:
* `POST /session/:sessionId/appium/device/long_press_keycode`
* :octicons-arrow-right-24: `mobile: pressKey` execute method :material-android: :material-coffee:
* `POST /session/:sessionId/appium/device/network_speed`
* :octicons-arrow-right-24: `mobile: networkSpeed` execute method :material-android: [^sim] :material-coffee: [^sim]
* `POST /session/:sessionId/appium/device/open_notifications`
* :octicons-arrow-right-24: `mobile: statusBar` execute method :material-android: :material-coffee:
* :octicons-arrow-right-24: `mobile: openNotifications` execute method :material-android:
* `POST /session/:sessionId/appium/device/power_ac`
* :octicons-arrow-right-24: `mobile: powerAC` execute method :material-android: [^sim] :material-coffee: [^sim]
* `POST /session/:sessionId/appium/device/power_capacity`
* :octicons-arrow-right-24: `mobile: powerCapacity` execute method :material-android: [^sim] :material-coffee: [^sim]
* `POST /session/:sessionId/appium/device/press_keycode`
* :octicons-arrow-right-24: `mobile: keys` execute method :material-apple: (iPadOS only)
* :octicons-arrow-right-24: `mobile: pressKey` execute method :material-android: :material-coffee:
* :octicons-arrow-right-24: `macos: keys` execute method :material-apple-finder:
* :octicons-arrow-right-24: `windows: keys` execute method :material-microsoft-windows:
* `POST /session/:sessionId/appium/device/send_sms`
* :octicons-arrow-right-24: `mobile: sendSms` execute method :material-android: [^sim] :material-coffee: [^sim]
* `POST /session/:sessionId/appium/device/set_clipboard`
* :octicons-arrow-right-24: `mobile: setClipboard` execute method :material-apple: :material-android: :material-coffee:
* :octicons-arrow-right-24: `mobile: setPasteboard` execute method :material-apple: [^sim]
* :octicons-arrow-right-24: `windows: setClipboard` execute method :material-microsoft-windows:
* `POST /session/:sessionId/appium/device/shake`
* :octicons-arrow-right-24: `mobile: shake` execute method :material-apple: [^sim]
* `POST /session/:sessionId/appium/device/start_activity`
* :octicons-arrow-right-24: `mobile: startActivity` execute method :material-android: :material-coffee:
* `GET /session/:sessionId/appium/device/system_bars`
* :octicons-arrow-right-24: `mobile: deviceScreenInfo` execute method :material-apple:
* :octicons-arrow-right-24: `mobile: getSystemBars` execute method :material-android: :material-coffee:
* `POST /session/:sessionId/appium/device/toggle_airplane_mode`
* :octicons-arrow-right-24: `mobile: setConnectivity` execute method :material-android: :material-coffee:
* `POST /session/:sessionId/appium/device/toggle_data`
* :octicons-arrow-right-24: `mobile: setConnectivity` execute method :material-android: :material-coffee:
* `POST /session/:sessionId/appium/device/toggle_location_services`
* :octicons-arrow-right-24: `mobile: toggleGps` execute method :material-android: :material-coffee:
* `POST /session/:sessionId/appium/device/toggle_wifi`
* :octicons-arrow-right-24: `mobile: setConnectivity` execute method :material-android: :material-coffee:
* `POST /session/:sessionId/appium/device/unlock`
* :octicons-arrow-right-24: `mobile: unlock` execute method :material-apple: :material-android: :material-coffee:
* `POST /session/:sessionId/appium/element/:elementId/value`
* :octicons-arrow-right-24: `POST /session/:sessionId/element/:elementId/value` :simple-appium:
* `POST /session/:sessionId/appium/element/:elementId/replace_value`
* :octicons-arrow-right-24: `POST /session/:sessionId/element/:elementId/value` :simple-appium:
* `POST /session/:sessionId/appium/getPerformanceData`
* :octicons-arrow-right-24: `mobile: getPerformanceData` execute method :material-android: :material-coffee:
* `POST /session/:sessionId/appium/performanceData/types`
* :octicons-arrow-right-24: `mobile: getPerformanceDataTypes` execute method :material-android: :material-coffee:
* `POST /session/:sessionId/appium/receive_async_response`
* :octicons-arrow-right-24: `POST /session/:sessionId/execute/async` :simple-appium:
* `POST /session/:sessionId/appium/simulator/toggle_touch_id_enrollment`
* :octicons-arrow-right-24: `mobile: enrollBiometric` execute method :material-apple: [^sim]
* `POST /session/:sessionId/appium/simulator/touch_id`
* :octicons-arrow-right-24: `mobile: sendBiometricMatch` execute method :material-apple: [^sim]
* `POST /session/:sessionId/appium/start_recording_screen`
* :octicons-check-24: Moved to drivers: :material-apple: :material-android: :material-coffee: :material-apple-finder: :material-microsoft-windows:
* :octicons-arrow-right-24: `mobile: startXCTestScreenRecording` execute method :material-apple:
* :octicons-arrow-right-24: `mobile: startMediaProjectionRecording` execute method :material-android: :material-coffee:
* :octicons-arrow-right-24: `macos: startRecordingScreen` or `macos: startNativeScreenRecording` execute methods :material-apple-finder:
* :octicons-arrow-right-24: `windows: startRecordingScreen` execute method :material-microsoft-windows:
* `POST /session/:sessionId/appium/stop_recording_screen`
* :octicons-check-24: Moved to drivers: :material-apple: :material-android: :material-coffee: :material-apple-finder: :material-microsoft-windows:
* :octicons-arrow-right-24: `mobile: stopXCTestScreenRecording` execute method :material-apple:
* :octicons-arrow-right-24: `mobile: stopMediaProjectionRecording` execute method :material-android: :material-coffee:
* :octicons-arrow-right-24: `macos: stopRecordingScreen` or `macos: stopNativeScreenRecording` execute methods :material-apple-finder:
* :octicons-arrow-right-24: `windows: stopRecordingScreen` execute method :material-microsoft-windows:
* `GET /session/:sessionId/application_cache/status`
* :octicons-no-entry-24: JSONWP protocol command with no direct replacement
* `POST /session/:sessionId/buttondown`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: [W3C Actions API](https://www.selenium.dev/documentation/webdriver/actions_api/) (`pointerDown`) :simple-appium:
* :octicons-arrow-right-24: `windows: keys` execute method :material-microsoft-windows:
* `POST /session/:sessionId/buttonup`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: W3C Actions API (`pointerUp`) :simple-appium:
* :octicons-arrow-right-24: `windows: keys` execute method :material-microsoft-windows:
* `POST /session/:sessionId/click`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: W3C Actions API (`pointerDown` & `pointerUp`) :simple-appium:
* `POST /session/:sessionId/dismiss_alert`
* :octicons-arrow-right-24: `POST /session/:sessionId/alert/dismiss` :simple-appium:
* `POST /session/:sessionId/doubleclick`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: W3C Actions API (`pointerDown` & `pointerUp`) :simple-appium:
* `POST /session/:sessionId/element/active`
* :octicons-arrow-right-24: `GET /session/:sessionId/element/active` :simple-appium:
* `GET /session/:sessionId/element/:elementId/equals/:otherId`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* `GET /session/:sessionId/element/:elementId/location`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: `GET /session/:sessionId/element/:elementId/rect` :simple-appium:
* `GET /session/:sessionId/element/:elementId/location_in_view`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* `GET /session/:sessionId/element/:elementId/pageIndex`
* :octicons-no-entry-24: MJSONWP protocol command with no direct replacement
* `GET /session/:sessionId/element/:elementId/size`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: `GET /session/:sessionId/element/:elementId/rect` :simple-appium:
* `POST /session/:sessionId/element/:elementId/submit`
* :octicons-no-entry-24: JSONWP protocol command with no direct replacement
* `POST /session/:sessionId/execute`
* :octicons-arrow-right-24: `POST /session/:sessionId/execute/sync` :simple-appium:
* `POST /session/:sessionId/execute_async`
* :octicons-arrow-right-24: `POST /session/:sessionId/execute/async` :simple-appium:
* `POST /session/:sessionId/keys`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: W3C Actions API (`keyDown` & `keyUp`) :simple-appium:
* Selenium-based clients can also use [Send Keys](https://www.selenium.dev/documentation/webdriver/actions_api/keyboard/#send-keys)
* `GET /session/:sessionId/local_storage`
* :octicons-no-entry-24: JSONWP protocol command with no direct replacement
* `POST /session/:sessionId/local_storage`
* :octicons-no-entry-24: JSONWP protocol command with no direct replacement
* `DELETE /session/:sessionId/local_storage`
* :octicons-no-entry-24: JSONWP protocol command with no direct replacement
* `GET /session/:sessionId/local_storage/key/:key`
* :octicons-no-entry-24: JSONWP protocol command with no direct replacement
* `DELETE /session/:sessionId/local_storage/key/:key`
* :octicons-no-entry-24: JSONWP protocol command with no direct replacement
* `GET /session/:sessionId/local_storage/size`
* :octicons-no-entry-24: JSONWP protocol command with no direct replacement
* `POST /session/:sessionId/log`
* :octicons-arrow-right-24: `POST /session/:sessionId/se/log` :simple-appium:
* `GET /session/:sessionId/log/types`
* :octicons-arrow-right-24: `GET /session/:sessionId/se/log/types` :simple-appium:
* `POST /session/:sessionId/moveto`
* :octicons-arrow-right-24: W3C Actions API (`pointerMove`) :simple-appium:
* Selenium-based clients can also use [Move by Offset](https://www.selenium.dev/documentation/webdriver/actions_api/mouse/#move-by-offset)
* `GET /session/:sessionId/screenshot/:elementId`
* :octicons-arrow-right-24: `GET /session/:sessionId/element/:elementId/screenshot` :simple-appium:
* `GET /session/:sessionId/session_storage`
* :octicons-no-entry-24: JSONWP protocol command with no direct replacement
* `POST /session/:sessionId/session_storage`
* :octicons-no-entry-24: JSONWP protocol command with no direct replacement
* `DELETE /session/:sessionId/session_storage`
* :octicons-no-entry-24: JSONWP protocol command with no direct replacement
* `GET /session/:sessionId/session_storage/key/:key`
* :octicons-no-entry-24: JSONWP protocol command with no direct replacement
* `DELETE /session/:sessionId/session_storage/key/:key`
* :octicons-no-entry-24: JSONWP protocol command with no direct replacement
* `GET /session/:sessionId/session_storage/size`
* :octicons-no-entry-24: JSONWP protocol command with no direct replacement
* `POST /session/:sessionId/timeouts/async_script`
* :octicons-arrow-right-24: `POST /session/:sessionId/timeouts` :simple-appium:
* `POST /session/:sessionId/timeouts/implicit_wait`
* :octicons-arrow-right-24: `POST /session/:sessionId/timeouts` :simple-appium:
* `POST /session/:sessionId/touch/click`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: W3C Actions API (`pointerDown` & `pointerUp`) :simple-appium:
* Selenium-based clients can also use [Click and Release](https://www.selenium.dev/documentation/webdriver/actions_api/mouse/#click-and-release)
* :octicons-arrow-right-24: `mobile: tap` or `mobile: tapWithNumberOfTaps` execute methods :material-apple:
* :octicons-arrow-right-24: `mobile: clickGesture` execute method :material-android:
* :octicons-arrow-right-24: `mobile: clickAction` execute method :material-coffee:
* :octicons-arrow-right-24: `macos: click`, `macos: rightClick`, `macos: press` or `macos: tap` execute methods :material-apple-finder:
* :octicons-arrow-right-24: `windows: click` execute method :material-microsoft-windows:
* `POST /session/:sessionId/touch/doubleclick`
* :octicons-arrow-right-24: W3C Actions API (`pointerDown` & `pointerUp`) :simple-appium:
* Selenium-based clients can also use [Double Click](https://www.selenium.dev/documentation/webdriver/actions_api/mouse/#double-click)
* :octicons-arrow-right-24: `mobile: doubleTap` or `mobile: tapWithNumberOfTaps` execute methods :material-apple:
* :octicons-arrow-right-24: `mobile: doubleClickGesture` execute method :material-android:
* :octicons-arrow-right-24: `mobile: clickAction` execute method :material-coffee:
* :octicons-arrow-right-24: `macos: doubleClick` or `macos: doubleTap` execute methods :material-apple-finder:
* :octicons-arrow-right-24: `windows: click` execute method :material-microsoft-windows:
* `POST /session/:sessionId/touch/down`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: W3C Actions API (`pointerDown`) :simple-appium:
* :octicons-arrow-right-24: `windows: keys` execute method :material-microsoft-windows:
* `POST /session/:sessionId/touch/flick`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: W3C Actions API (`pointerDown`, `pointerMove` & `pointerUp`) :simple-appium:
* :octicons-arrow-right-24: `mobile: flingGesture` execute method :material-android:
* `POST /session/:sessionId/touch/longclick`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: W3C Actions API (`pointerDown`, `pause` & `pointerUp`) :simple-appium:
* :octicons-arrow-right-24: `mobile: touchAndHold` execute method :material-apple:
* :octicons-arrow-right-24: `mobile: longClickGesture` execute method :material-android:
* :octicons-arrow-right-24: `mobile: clickAction` execute method :material-coffee:
* :octicons-arrow-right-24: `macos: press` execute method :material-apple-finder:
* :octicons-arrow-right-24: `windows: click` execute method :material-microsoft-windows:
* `POST /session/:sessionId/touch/multi/perform`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: `POST /session/:sessionId/actions` :simple-appium:
* `POST /session/:sessionId/touch/move`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: W3C Actions API (`pointerMove`) :simple-appium:
* Selenium-based clients can also use [Move by Offset](https://www.selenium.dev/documentation/webdriver/actions_api/mouse/#move-by-offset)
* `POST /session/:sessionId/touch/perform`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: `POST /session/:sessionId/actions` :simple-appium:
* `POST /session/:sessionId/touch/scroll`
* :octicons-arrow-right-24: W3C Actions API (`pointerDown`, `pointerMove` & `pointerUp`) :simple-appium:
* :octicons-arrow-right-24: `mobile: scroll` or `mobile: swipe` execute methods :material-apple:
* :octicons-arrow-right-24: `mobile: scrollGesture` or `mobile: swipeGesture` execute methods :material-android:
* :octicons-arrow-right-24: `mobile: swipe` execute method :material-coffee:
* :octicons-arrow-right-24: `macos: scroll` or `macos: swipe` execute methods :material-apple-finder:
* :octicons-arrow-right-24: `windows: scroll` execute method :material-microsoft-windows:
* `POST /session/:sessionId/touch/up`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: W3C Actions API (`pointerUp`) :simple-appium:
* :octicons-arrow-right-24: `windows: keys` execute method :material-microsoft-windows:
* `GET /session/:sessionId/window_handle`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: `GET /session/:sessionId/window` :simple-appium:
* `GET /session/:sessionId/window_handles`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: `GET /session/:sessionId/window/handles` :simple-appium:
* `GET /session/:sessionId/window/handle`
* :octicons-arrow-right-24: `GET /session/:sessionId/window` :simple-appium:
* `POST /session/:sessionId/window/:windowhandle/maximize`
* :octicons-arrow-right-24: `POST /session/:sessionId/window/maximize` :simple-appium:
* :fontawesome-solid-triangle-exclamation: Only supported for the current window
* `GET /session/:sessionId/window/:windowhandle/position`
* :octicons-arrow-right-24: `GET /session/:sessionId/window/rect` :simple-appium:
* :fontawesome-solid-triangle-exclamation: Only supported for the current window
* `POST /session/:sessionId/window/:windowhandle/position`
* :octicons-arrow-right-24: `POST /session/:sessionId/window/rect` :simple-appium:
* :fontawesome-solid-triangle-exclamation: Only supported for the current window
* `GET /session/:sessionId/window/:windowhandle/size`
* :octicons-check-24: Moved to drivers: :material-microsoft-windows:
* :octicons-arrow-right-24: `GET /session/:sessionId/window/rect` :simple-appium:
* :fontawesome-solid-triangle-exclamation: Only supported for the current window
### Modified
The following are all endpoints modified in Appium 3, by removing handling for old or unused
parameters (note that no new parameters have been added). Each endpoint lists the parameters it no
longer accepts, as well as the parameters it continues to accept in Appium 3.
* `POST /session`
* :octicons-x-24: `desiredCapabilities`, `requiredCapabilities`
* :octicons-check-24: `capabilities`
* `POST /session/:sessionId/alert/text`
* :octicons-x-24: `value`
* :octicons-check-24: `text`
* `GET /session/:sessionId/appium/device/system_time`
* :octicons-x-24: `format`
* :octicons-check-24: None
* `POST /session/:sessionId/element/:elementId/value`
* :octicons-x-24: `value`
* :octicons-check-24: `text`
* `POST /session/:sessionId/timeouts`
* :octicons-x-24: `type`, `ms`
* :octicons-check-24: `script`, `pageLoad`, `implicit`
* `POST /session/:sessionId/window`
* :octicons-x-24: `name`
* :octicons-check-24: `handle`
[^sim]: Supported in emulators/simulators only
+36 -165
View File
@@ -3,200 +3,71 @@ 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 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:
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 Appium's features if
all the following are 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 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.
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 that are in charge of starting the Appium server) to _explicitly opt-in_ to these features.
(Third-party driver and plugin authors can also [hide behaviour behind security
flags](../developing/build-drivers.md).)
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.
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.
## Security Server Args
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:
The [Server CLI Args](../cli/args.md) doc outlines three relevant arguments which may be passed to
Appium when starting it from the command line:
|<div style="width:10em">Parameter</div>|Description|
|---------------------------------------|-----------|
|`--relaxed-security`|Turns on _all_ insecure features, except those blocked by `--deny-insecure`|
|`--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`|
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 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.
|`--relaxed-security` |Setting this flag turns on _all_ insecure features (unless blocked by `--deny-insecure`; see below)|
|`--allow-insecure` |Setting this flag to a comma-separated list of feature names or a path to a file containing a feature list (each name on a separate line) will allow _only_ the features listed. For example, `--allow-insecure=adb_shell` will cause _only_ the ADB shell execution feature to be enabled. This is true _unless_ `--relaxed-security` is also used, in which case all features will still be enabled. It makes no sense to combine this flag with `--relaxed-security`.|
|`--deny-insecure` |This flag can likewise be set to a comma-separated list of feature names, or a path to a feature file. Any features listed here will be _disabled_, regardless of whether `--relaxed-security` is set and regardless of whether the names are also listed with `--allow-insecure`.|
## Insecure Features
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.
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:
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.
|<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 to send a request which has multiple Appium commands.|Execute Driver Plugin|
!!! note
## Driver-scope security
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).
Since Appium server version 2.12.3 there is a possibility to prefix each feature name with the corresponding automationName where it is going to be applied. For example, if you provide the following features to allow:
`uiautomator2:adb_shell,xcuitest:get_server_logs,*:record_audio`, then the `adb_shell` would only be allowed
for the UiAutomator2 driver, `get_server` - for the XCUITest driver and the `record_audio` one - for
all installed drivers. Feature names provided without explicit automation name prefix are equivalent to
these having the `*:` prefix. The same feature naming rule applies to the list of denied features.
## Examples
Turn on the `foo` feature only for the `first` driver:
To turn on the `get_server_logs` feature for my Appium server, I could start it like this:
```bash
appium --allow-insecure=first:foo
appium --allow-insecure=get_server_logs
```
Turn on the `foo` feature for all drivers:
To turn on multiple features:
```bash
appium --allow-insecure='*:foo'
appium --allow-insecure=get_server_logs,record_audio
```
Turn on the `foo` feature for all drivers _except_ `first`:
To allow all features except one:
```bash
appium --allow-insecure='*:foo' --deny-insecure=first:foo
appium --relaxed-security --deny-insecure=adb_shell
```
Turn on all features _except_ `foo` for all drivers:
```bash
appium --relaxed-security --deny-insecure='*:foo'
```
Turn on multiple insecure features for specific drivers:
```bash
appium --allow-insecure=uiautomator2:adb_shell,xcuitest:get_server_logs
```
## Restricting Remote App URLs
Several drivers accept a URL instead of a local path in capabilities such as `appium:app`, in which
case the Appium server downloads the application package from that URL before starting the session.
By default, any `http:` or `https:` URL is accepted. Server hosts who want to control which URLs
their server is allowed to download from can do so with the `--app-url-rules` argument (or the
`server.app-url-rules` property in a [configuration file](./config.md)). Its value is a JSON object
(or a path to a JSON file) with any of the following properties:
|<div style="width:10em">Rule</div>|Description|Default|
|----------------------------------|-----------|-------|
|`allow`|List of hostname patterns, IP addresses, or CIDR subnets. If non-empty, a hostname or its resolved address must match _at least one_|`[]`|
|`deny`|List of hostname patterns, IP addresses, or CIDR subnets. A matching hostname or resolved address is rejected, even if an `allow` rule also matches|`[]`|
|`httpsOnly`|Only accept `https:` URLs|`false`|
|`allowCredentials`|Accept URLs containing a username and/or password (e.g. `https://user:pass@host/app.apk`)|`true`|
|`maxRedirects`|Maximum number of HTTP redirects to follow while downloading. Set to `0` to reject any redirect|`21`|
Hostnames are normalized (lowercased, converted to Punycode, trailing dot removed) before matching
and resolved on every download. Address rules apply to literal addresses and all dynamically
resolved IPv4/IPv6 addresses. The rules are also applied to every redirect, so redirects cannot be
used to escape them. If a URL violates any rule, the session is not created and a generic error
is returned. The violated rule is deliberately neither reported to the client nor written to the
server log, since server logs are often handed over to clients as well. URL schemes, ports, paths,
queries, and fragments are not matched.
Hostname patterns use the [picomatch](https://github.com/micromatch/picomatch#globbing-features)
glob syntax and are matched against the whole hostname:
|Pattern|Matches|
|-------|-------|
|`artifacts.example.com`|Exactly this hostname|
|`*.example.com`|Any subdomain of `example.com` (including nested ones, like `a.b.example.com`), but not `example.com` itself|
|`*example.com`|Any hostname ending with `example.com`, including `example.com` itself|
|`apps.{staging,prod}.example.com`|`apps.staging.example.com` and `apps.prod.example.com`|
|`build-?.example.com`|`build-1.example.com`, `build-a.example.com`, etc.|
|`node[0-9].example.com`|`node0.example.com` to `node9.example.com`|
IP address rules match a single address (`192.0.2.10`, `2001:db8::1`) or a whole subnet in CIDR
notation (`10.0.0.0/8`, `2001:db8::/32`). IPv4 rules also match IPv4-mapped IPv6 addresses
(e.g. `::ffff:10.1.2.3`).
!!! note
These rules only apply to URLs the server downloads via the standard app configuration helper,
which is used for `appium:app` and similar capabilities by all official drivers. Drivers may
define custom capabilities with URLs that are processed differently and thus are not covered.
!!! note
If the server downloads applications through an HTTP proxy (configured via the `HTTP_PROXY`,
`HTTPS_PROXY` and `NO_PROXY` environment variables), the proxy resolves the destination host
itself, so rules containing IP addresses or subnets cannot be enforced for proxied downloads.
Such downloads are rejected; either exclude the download hosts from proxying via `NO_PROXY`
or only use hostname-based rules.
### Examples
Only allow HTTPS downloads from an internal artifact server, without credentials in the URL and
without following redirects:
```bash
appium --app-url-rules='{"allow": ["artifacts.example.com", "10.0.0.0/8"], "httpsOnly": true, "allowCredentials": false, "maxRedirects": 0}'
```
The same configuration as part of a config file:
```yaml
server:
app-url-rules:
allow:
- 'artifacts.example.com'
- '10.0.0.0/8'
httpsOnly: true
allowCredentials: false
maxRedirects: 0
```
Allow downloads from any subdomain of `example.com` and from two IPv6 subnets, except from the
staging environment:
```yaml
server:
app-url-rules:
allow:
- '*.example.com'
- '2001:db8:1::/48'
- '2001:db8:2::/48'
deny:
- '*.staging.example.com'
```
Allow downloads from anywhere, except from the server itself, private networks, link-local
addresses (such as cloud metadata services), and any `.internal` hostname:
```yaml
server:
app-url-rules:
deny:
- 'localhost'
- '*.internal'
- '127.0.0.0/8'
- '10.0.0.0/8'
- '172.16.0.0/12'
- '192.168.0.0/16'
- '169.254.0.0/16'
- '::1/128'
- 'fc00::/7'
- 'fe80::/10'
```
The rules in the last example are applied to the addresses each hostname resolves to, so they
cannot be bypassed via DNS. Note that the `deny` list also blocks any download from the server's
own private network, so a private artifact server must be excluded from the `deny` rules in order
to work.
+7 -6
View File
@@ -2,7 +2,7 @@
hide:
- toc
title: SSL/TLS Support
title: SSL/TLS/SPDY Support
---
Appium 2.2 introduces the option to start the Appium server with SSL/TLS support.
@@ -19,14 +19,15 @@ Both arguments must be provided and should contain paths to a valid
[X509 PEM](https://www.ssl.com/guide/pem-der-crt-and-cer-x-509-encodings-and-conversions/)
certificate and its corresponding private key.
After the server is started use the `https` protocol and a client supporting SSL/TLS to
communicate to it.
After the server is started use the `https` protocol and a client supporting SSL/TLS or
[SPDY](https://en.wikipedia.org/wiki/SPDY) to communicate to it.
### Supported Features
Once a secure server socket is established it uses Node.js' native
[`https`](https://nodejs.org/api/https.html) module to serve connections. All insecure client
connections will be rejected by the server.
Once a secure server socket is established it supports the following protocols:
`['h2', 'spdy/3.1', 'spdy/3', 'spdy/2', 'http/1.1', 'http/1.0']`. See
[the SPDY node module documentation](https://www.npmjs.com/package/spdy) to get more details about
its features. All insecure client connections will be rejected by the server.
### Self-Signed Certificates
+5 -11
View File
@@ -33,12 +33,6 @@ Android TV, Samsung), and more!
<img src="assets/images/sponsor-logo-browserstack-light.png#only-light" style="width: 220px;" />
</a>
</div>
<div class="homepageSponsor">
<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>
</div>
@@ -49,11 +43,11 @@ Android TV, Samsung), and more!
- Check out the [__Introduction__](./intro/index.md) to make sure you understand the key concepts
- Go through the [__Quickstart__](./quickstart/index.md) to get set up and run a basic Android test
- Visit the [__Ecosystem__](./ecosystem/index.md) page for a list of drivers, clients and plugins you may want to use
- Consult the [__Reference__](./reference/index.md) page for information on the Appium CLI and supported endpoints
- Read the different [__Guides__](./guides/migrating-2-to-3.md) for a variety of instructions, tips and tricks
- Check out various third-party [__Resources__](./resources/index.md) to explore Appium around the web
- Refer to the [__CLI Reference__](./cli/index.md) for using Appium from the command line
- See the [__Command Reference__](./commands/index.md) for a list of commands exposed by Appium and plugins
- Read the different [__Guides__](./guides/migrating-1-to-2.md) for a variety of instructions, tips and tricks
- Check out various third-party [__Resources__](./resources.md) to explore Appium around the web
- For creating your own Appium extensions, see the [__Developer__](./developing/index.md) documentation
- For contributions to Appium itself, refer to the [__Contributing__](./contributing/index.md) page
- Have a look at the [__Appium Blog__](./blog/index.md) to learn what's new in the project
- For contributions to Appium itself, refer to the [__Contributing__](./contributing.md) page
</div>
+4 -4
View File
@@ -107,7 +107,7 @@ differently from one another. The tools and requirements for building and using
different platforms are completely different. And so Appium lets you use just the drivers that you
need for your automation tasks. Choosing drivers and installing them so that you can use them with
your Appium instance is so important that Appium has its very own [CLI for managing
drivers](../reference/cli/extensions.md).
drivers](../cli/extensions.md).
So, to answer our original question, the way that Appium provides access to automation capabilities
for a given platform is that the Appium team (or anyone else[^3]) writes a *driver* for that
@@ -190,9 +190,9 @@ will never have time to build. And so, with Appium 2, Appium has released a plug
enables anyone to build and share modules that change how Appium works!
In the same way that drivers are easily shareable and consumable via the Appium driver CLI, plugins
can be published and consumed via a parallel [Plugin CLI](../reference/cli/extensions.md). Plugins
can do all sorts of things, for example adding the ability for Appium to find and interact with
screen regions based on a template image (as in the [`images`
can be published and consumed via a parallel [Plugin CLI](../cli/extensions.md). Plugins can do all
sorts of things, for example adding the ability for Appium to find and interact with screen regions
based on a template image (as in the [`images`
plugin](https://github.com/appium/appium/tree/master/packages/images-plugin)). There are very few
limitations on what you can do with plugins, so you might also be interested in learning how to
[Build Plugins](../developing/build-plugins.md) in Node.js that can be used with Appium.
-10
View File
@@ -39,16 +39,6 @@ So, for example, the `Find Element` command corresponds to an HTTP `POST` reques
endpoint `/session/:sessionid/element` (where in this case, `:sessionid` is a placeholder for the
unique session ID generated by the server in a previous call to `Create Session`).
If the client disconnects before Appium finishes sending a `Create Session` response and the
request has no `X-Idempotency-Key`, Appium deletes the new session once driver setup completes.
Setup is not interrupted. With an accepted idempotency key, a retry that arrives before setup
finishes waits for the same session ID, or the same error if setup failed. If the original client
and all waiting retries disconnect before setup finishes, Appium deletes the new session and
discards its cached result; a later retry starts a new session. Otherwise, Appium keeps the session
and caches its response for replay while it remains in the bounded, in-memory idempotency cache.
Disconnecting after a response was sent, or during a command in an existing session, does not
automatically end that session. Use `Delete Session` when you are done.
This information is primarily useful for people developing technology that works with the WebDriver
spec. It's not particularly useful for people trying to write Appium or Selenium tests. When you
write an Appium test, you want to use a programming language you're familiar with. Luckily, there
+1 -1
View File
@@ -19,7 +19,7 @@ Appium, called `BaseDriver`. You could have something very close to a "working"
very simple lines of code:
```js
import {BaseDriver} from '@appium/base-driver'
import BaseDriver from '@appium/base-driver'
class MyNewDriver extends BaseDriver {
}
+7 -21
View File
@@ -157,7 +157,8 @@ it was easy for users or third-party developers to build their own Appium
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.
app automation and Youi.tv app automation, respectively. Who knows what
platforms will be added next?
## Appium To The People
@@ -171,26 +172,11 @@ 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.
Eventually, the JS Foundation merged into the [OpenJS Foundation](https://openjsf.org),
and Appium became an Impact Project in the foundation.
Eventually, the JS Foundation merged into the [OpenJS Foundation](https://openjsf.org), and Appium
is currently an Impact Project in the foundation.
## 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.
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 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.
Appium 2 was released in 2023, with a new focus on Appium as an ecosystem rather than a singular
project. Drivers and plugins can be developed and shared by anyone, opening up a world of
possibilities for automation-related development for platforms far beyond iOS and Android.
+1 -1
View File
@@ -2,7 +2,7 @@
hide:
- toc
title: Getting Started
title: Quickstart Intro
---
Let's get up and running with Appium! To successfully use this quickstart, it's recommended that
@@ -21,7 +21,7 @@ npm install -g appium
## Starting Appium
Appium can be started [using the command line](../reference/cli/index.md):
Appium can be started [using the command line](../cli/index.md):
```
appium
@@ -8,9 +8,9 @@ title: System Requirements
The basic requirements for the Appium server are:
* A macOS, Linux, or Windows operating system
* [Node.js](https://nodejs.org) version in the [SemVer](https://semver.org) range `^20.19.0 || ^22.12.0 || >=24.0.0`
* [Node.js](https://nodejs.org) version in the [SemVer](https://semver.org) range `^14.17.0 || ^16.13.0 || >=18.0.0`
* LTS is recommended
* [`npm`](https://npmjs.com) version `>=10` (`npm` is usually bundled with Node.js, but can be upgraded
* [`npm`](https://npmjs.com) version `>=8` (`npm` is usually bundled with Node.js, but can be upgraded
independently)
By itself, Appium is relatively lightweight and doesn't have significant disk space or RAM
@@ -26,4 +26,4 @@ require the developer toolchain and SDKs for that platform to be installed.
In order to assist with driver requirements, each (official) driver comes with the Appium Doctor tool,
which allows to verify if all requirements have been set up. Learn more about how to use this tool in
the [Command-Line Usage documentation](../reference/cli/extensions.md#doctor).
the [Command-Line Usage documentation](../cli/extensions.md#doctor).
+105 -105
View File
@@ -1,105 +1,105 @@
---
hide:
- toc
title: Write a Test (.NET)
---
The [Appium .NET Client](https://github.com/appium/dotnet-client/) is
an official Appium client in C#. This driver is an extension of the Selenium C# client. It has all the functionalities of the regular driver, but add Appium-specific methods on top of this. The driver is available on the public NuGet Gallery as [Appium.WebDriver](https://www.nuget.org/packages/Appium.WebDriver/).
Now, we get inside the directory and create a new [NUnit](https://nunit.org/) project. We will also add the references to the Appium.Net driver, and other dependencies.
```bash
cd dotnet-client
dotnet new nunit --name appiumtest
cd appiumtest
# This will install the latest 5.x version
dotnet add package Appium.WebDriver --prerelease
dotnet add package Newtonsoft.Json --version 13.0.3
```
Once this is done, your project should have a placeholder file `UnitTest1.cs`. We will replace the code to include the OpenQA namespaces, an initialization of the driver, and the actual test.
```C# title="UnitTest1.cs"
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Android;
using OpenQA.Selenium.Appium.Enums;
namespace appiumtest;
public class Tests
{
private AndroidDriver _driver;
[OneTimeSetUp]
public void SetUp()
{
var serverUri = new Uri(Environment.GetEnvironmentVariable("APPIUM_HOST") ?? "http://127.0.0.1:4723/");
var driverOptions = new AppiumOptions() {
AutomationName = AutomationName.AndroidUIAutomator2,
PlatformName = "Android",
DeviceName = "Android Emulator",
};
driverOptions.AddAdditionalAppiumOption("appPackage", "com.android.settings");
driverOptions.AddAdditionalAppiumOption("appActivity", ".Settings");
// NoReset assumes the app com.google.android is preinstalled on the emulator
driverOptions.AddAdditionalAppiumOption("noReset", true);
_driver = new AndroidDriver(serverUri, driverOptions, TimeSpan.FromSeconds(180));
_driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
}
[OneTimeTearDown]
public void TearDown()
{
_driver.Dispose();
}
[Test]
public void TestFindApps()
{
_driver.StartActivity("com.android.settings", ".Settings");
_driver.FindElement(By.XPath("//*[@text='Apps']")).Click();
}
}
```
!!! note
It's not within the scope of this guide to give a complete run-down on the dotnet client
library or everything that's happening here, so we'll leave the code itself unexplained in
detail for now. You may want to read up particularly on Appium
[Capabilities](../guides/caps.md) in addition to familiarizing yourself with the
[dotnet client driver documentation](https://github.com/appium/dotnet-client/) for a fuller explanation
of the various API commands you see and what their purpose is.
Basically, this code is doing the following:
1. Defining a set of "Capabilities" (parameters) to send to the Appium server so Appium knows what
kind of thing you want to automate. Some of these parameters can be overridden using environment variables.
1. Starting an Appium session on the built-in Android settings app.
1. Finding the "Apps" list item and clicking it.
1. Ending the Appium session.
That's it! Let's give it a try. Before you run the test, make sure that you have an Appium server
running in another terminal session, otherwise you'll get an error about not being able to connect
to one. Then, you can execute the script:
```bash
dotnet test
# Example output:
# Starting test execution, please wait...
# A total of 1 test files matched the specified pattern.
# Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: 323 ms - appiumtest.dll (net7.0)
```
If all goes well, you'll see the Settings app open up and navigate to the "Apps" view in the emulator before the app closes again.
Congratulations, you've started your Appium journey! Read on for some [next steps](./next-steps.md) to explore.
---
hide:
- toc
title: Write a Test (.NET)
---
The [Appium .NET Client](https://github.com/appium/dotnet-client/) is
an official Appium client in C#. This driver is an extension of the Selenium C# client. It has all the functionalities of the regular driver, but add Appium-specific methods on top of this. The driver is available on the public NuGet Gallery as [Appium.WebDriver](https://www.nuget.org/packages/Appium.WebDriver/).
Now, we get inside the directory and create a new [NUnit](https://nunit.org/) project. We will also add the references to the Appium.Net driver, and other dependencies.
```bash
cd dotnet-client
dotnet new nunit --name appiumtest
cd appiumtest
# This will install the latest 5.x version
dotnet add package Appium.WebDriver --prerelease
dotnet add package Newtonsoft.Json --version 13.0.3
```
Once this is done, your project should have a placeholder file `UnitTest1.cs`. We will replace the code to include the OpenQA namespaces, an initialization of the driver, and the actual test.
```C# title="UnitTest1.cs"
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Android;
using OpenQA.Selenium.Appium.Enums;
namespace appiumtest;
public class Tests
{
private AndroidDriver _driver;
[OneTimeSetUp]
public void SetUp()
{
var serverUri = new Uri(Environment.GetEnvironmentVariable("APPIUM_HOST") ?? "http://127.0.0.1:4723/");
var driverOptions = new AppiumOptions() {
AutomationName = AutomationName.AndroidUIAutomator2,
PlatformName = "Android",
DeviceName = "Android Emulator",
};
driverOptions.AddAdditionalAppiumOption("appPackage", "com.android.settings");
driverOptions.AddAdditionalAppiumOption("appActivity", ".Settings");
// NoReset assumes the app com.google.android is preinstalled on the emulator
driverOptions.AddAdditionalAppiumOption("noReset", true);
_driver = new AndroidDriver(serverUri, driverOptions, TimeSpan.FromSeconds(180));
_driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
}
[OneTimeTearDown]
public void TearDown()
{
_driver.Dispose();
}
[Test]
public void TestBattery()
{
_driver.StartActivity("com.android.settings", ".Settings");
_driver.FindElement(By.XPath("//*[@text='Battery']")).Click();
}
}
```
!!! note
It's not within the scope of this guide to give a complete run-down on the dotnet client
library or everything that's happening here, so we'll leave the code itself unexplained in
detail for now. You may want to read up particularly on Appium
[Capabilities](../guides/caps.md) in addition to familiarizing yourself with the
[dotnet client driver documentation](https://github.com/appium/dotnet-client/) for a fuller explanation
of the various API commands you see and what their purpose is.
Basically, this code is doing the following:
1. Defining a set of "Capabilities" (parameters) to send to the Appium server so Appium knows what
kind of thing you want to automate. Some of these parameters can be overriden using environment variables.
1. Starting an Appium session on the built-in Android settings app.
1. Finding the "Battery" list item and clicking it.
1. Ending the Appium session.
That's it! Let's give it a try. Before you run the test, make sure that you have an Appium server
running in another terminal session, otherwise you'll get an error about not being able to connect
to one. Then, you can execute the script:
```bash
dotnet test
# Example output:
# Starting test execution, please wait...
# A total of 1 test files matched the specified pattern.
# Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: 323 ms - appiumtest.dll (net7.0)
```
If all goes well, you'll see the Settings app open up and navigate to the "Battery" view in the emulator before the app closes again.
Congratulations, you've started your Appium journey! Read on for some [next steps](./next-steps.md) to explore.
@@ -57,7 +57,7 @@ Basically, this code is doing the following:
1. Defining a set of "Capabilities" (parameters) to send to the Appium server so Appium knows what
kind of thing you want to automate.
1. Starting an Appium session on the built-in Android settings app.
1. Finding the "Apps" list item and clicking it.
1. Finding the "Battery" list item and clicking it.
1. Pausing for a moment purely for visual effect.
1. Ending the Appium session.
@@ -69,7 +69,7 @@ to one. Then, you can execute the script:
node test.js
```
If all goes well, you'll see the Settings app open up and navigate to the "Apps" view before the
If all goes well, you'll see the Settings app open up and navigate to the "Battery" view before the
app closes again.
Congratulations, you've started your Appium journey! Read on for some [next steps](./next-steps.md) to explore.
@@ -42,7 +42,7 @@ Basically, this code is doing the following:
1. Defining a set of "Capabilities" (parameters) to send to the Appium server so Appium knows what
kind of thing you want to automate.
1. Starting an Appium session on the built-in Android settings app.
1. Finding the "Apps" list item and clicking it.
1. Finding the "Battery" list item and clicking it.
1. Pausing for a moment purely for visual effect.
1. Ending the Appium session.
@@ -54,7 +54,7 @@ to one. Then, you can execute the script:
python test.py
```
If all goes well, you'll see the Settings app open up and navigate to the "Apps" view before the
If all goes well, you'll see the Settings app open up and navigate to the "Battery" view before the
app closes again.
Congratulations, you've started your Appium journey! Read on for some [next steps](./next-steps.md) to explore.
@@ -64,7 +64,7 @@ Basically, this code is doing the following:
1. Defining a set of "Capabilities" (parameters) to send to the Appium server so Appium knows what
kind of thing you want to automate.
1. Starting an Appium session on the built-in Android settings app.
1. Finding the "Apps" list item and clicking it.
1. Finding the "Battery" list item and clicking it.
1. Pausing for a moment purely for visual effect.
1. Ending the Appium session.
@@ -77,7 +77,7 @@ to one. Then, you can execute the script:
bundle exec ruby test.rb
```
If all goes well, you'll see the Settings app open up and navigate to the "Apps" view before the
If all goes well, you'll see the Settings app open up and navigate to the "Battery" view before the
app closes again.
Congratulations, you've started your Appium journey! Read on for some [next steps](./next-steps.md) to explore.
@@ -62,7 +62,7 @@ set up on your system, so you can get busy making Android apps if you want!
### Standard Install
Like all Appium drivers, the UiAutomator2 driver is installed via the [Appium Extension CLI](../reference/cli/extensions.md).
Like all Appium drivers, the UiAutomator2 driver is installed via the [Appium Extension CLI](../cli/extensions.md).
Since UiAutomator2 is maintained by the core Appium team, it has an 'official' driver name
(`uiautomator2`), which makes the installation simpler.
@@ -89,7 +89,7 @@ must be used to select this driver for use during an Appium session (in this cas
!!! note
In this quickstart we have used the [Extension CLI](../reference/cli/extensions.md) to install the
In this quickstart we have used the [Extension CLI](../cli/extensions.md) to install the
UiAutomator2 driver, but if you are incorporating Appium into a Node.js project, you might
prefer to use `npm` to manage Appium and its connected drivers. To learn more about this
technique, visit the guide on [managing Appium extensions](../guides/managing-exts.md).
@@ -108,7 +108,7 @@ Running this will install Appium's mobile-specific drivers: UiAutomator2, [XCUIT
(only if running macOS), and [Espresso](https://github.com/appium/appium-espresso-driver).
You can also use this command to batch install drivers for desktop applications or desktop browsers.
For more details on this, refer to the [Setup command documentation](../reference/cli/setup.md).
For more details on this, refer to the [Setup command documentation](../cli/setup.md).
### Validating the Install
@@ -1,504 +0,0 @@
---
title: Appium Protocol
---
<style>
ul[data-md-component="toc"] .md-nav {
display: none;
}
</style>
The following is a list of endpoints supported in Appium, that are defined in the Appium extension
of the W3C WebDriver protocol.
### getAppiumSessions
```
GET /appium/sessions
```
Retrieves information about all active server sessions.
!!! info
The `session_discovery` [insecure feature](../../guides/security.md) must be enabled to use this endpoint.
#### Response
`TimestampedMultiSessionData[]` - an array of session data objects. Each object has the following properties:
|Name|Description|Type|
|--|--|--|
|`capabilities`|Session capabilities|object|
|`created`|Session creation time (in milliseconds) as a Unix timestamp|number|
|`id`|Session ID|string|
### getAppiumSessionCapabilities
```
GET /session/:sessionId/appium/capabilities
```
Retrieves the [session capabilities](../../guides/caps.md).
#### Response
`SessionCapabilities` - an object with the following properties:
|Name|Description|Type|
|--|--|--|
|`capabilities`|Session capabilities|object|
### getSettings
```
GET /session/:sessionId/appium/settings
```
Retrieves the [current session settings](../../guides/settings.md).
#### Response
`Settings` - an object containing setting names and their values
### updateSettings
```
POST /session/:sessionId/appium/settings
```
Updates the specified session settings. Any other previously set settings will remain unchanged.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`settings`|Object containing the names and values of the settings to be updated|object|
#### Response
`null`
### listCommands
```
GET /session/:sessionId/appium/commands
```
Retrieves the URL endpoints and WebDriver BiDi commands supported in the current session.
#### Response
`ListCommandsResponse` - an object containing all supported endpoints and BiDi commands, grouped by
their origin (base Appium, driver-specific, or plugin-specific). Refer to [the type definition file](https://github.com/appium/appium/blob/master/packages/types/lib/command.ts)
for a detailed structure of this object.
### listExtensions
```
GET /session/:sessionId/appium/extensions
```
Retrieves the [execute methods](../../guides/execute-methods.md) supported in the current session.
#### Response
`ListExtensionsResponse` - an object containing all supported execute methods, grouped by their
origin (driver-specific or plugin-specific). Refer to [the type definition file](https://github.com/appium/appium/blob/master/packages/types/lib/command.ts)
for a detailed structure of this object.
### getCurrentAppiumContext
```
GET /session/:sessionId/appium/context
```
Retrieves the active application context.
#### Response
`string` - the name of the active context
### setAppiumContext
```
POST /session/:sessionId/appium/context
```
Sets an application context as the active context.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`name`|Name of the context to set as the active one|string|
#### Response
`null`
### getAppiumContexts
```
GET /session/:sessionId/appium/contexts
```
Retrieves all available application contexts.
#### Response
`string[]` - the names of available contexts
### getLogEvents
```
POST /session/:sessionId/appium/events
```
Retrieves events that have occurred in the current session. By default, only driver command
executions are recorded in the log, but drivers or plugins may define additional event types.
Clients can log events by using the [`logCustomEvent`](#logcustomevent) endpoint.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`type?`|One or more types to filter the returned events|string or array<string>|
#### Response
`EventHistory` - an object whose keys correspond to the types of logged events. Event types can be
grouped into three categories, as shown by the following example response:
```json
{
"commands": [
{ "cmd": "getStatus", "startTime": 1756887645447, "endTime": 1756887645454 }
],
"driverevent": [1756887645454],
"namespace:event": [1756887645454]
}
```
* The `commands` key is always included in the endpoint response. Its value is an array of objects,
where each object includes 3 parameters:
* `cmd`: name of the executed command
* `startTime`: the command execution start time (in milliseconds), as a Unix timestamp
* `endTime`: the command execution end time (in milliseconds), as a Unix timestamp
* Other non-namespaced keys are specific to driver/plugin implementations. Their value is an array
of event times (in milliseconds), as Unix timestamps.
* Namespaced keys can be added using the `logCustomEvent` endpoint, but may also be provided by
drivers/plugins. Their value is an array of event times (in milliseconds), as Unix timestamps.
### logCustomEvent
```
POST /session/:sessionId/appium/log_event
```
Logs a custom event, which can be retrieved using the [`getLogEvents`](#getlogevents) endpoint.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`vendor`|Name of the namespace (vendor) used to prefix the event|string|
|`event`|Name of the event|string|
#### Response
`null`
### getDeviceTime
```
POST /session/:sessionId/appium/device/system_time
```
Retrieves the current system time of the device under test.
#### Parameters
|Name|Description|Type|Default|
|--|--|--|--|
|`format?`|Format to use for the returned timestamp|string|`YYYY-MM-DDTHH:mm:ssZ`|
#### Response
`string` - the device time
### activateApp
```
POST /session/:sessionId/appium/device/activate_app
```
Activates an app on the device under test.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`appId` or `bundleId`|App identifier such as Android app package or iOS bundle ID|string|
|`options?`|Driver-specific launch options|unknown|
#### Response
`void`
### terminateApp
```
POST /session/:sessionId/appium/device/terminate_app
```
Terminates an app on the device under test.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`appId` or `bundleId`|App identifier such as Android app package or iOS bundle ID|string|
|`options?`|Driver-specific termination options|unknown|
#### Response
`void`
### queryAppState
```
POST /session/:sessionId/appium/device/app_state
```
Retrieves the state of an app on the device under test.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`appId` or `bundleId`|App identifier such as Android app package or iOS bundle ID|string|
#### Response
`number` - an integer value indicating the app state:
|Number|App State|
|--|--|
|`0`|Not installed|
|`1`|Not running|
|`2`|Running in background suspended|
|`3`|Running in background|
|`4`|Running in foreground|
### installApp
```
POST /session/:sessionId/appium/device/install_app
```
Installs an app on the device under test.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`appPath`|Absolute local filepath or URL to an app file|string|
|`options?`|Driver-specific install options|unknown|
#### Response
`void`
### removeApp
```
POST /session/:sessionId/appium/device/remove_app
```
Uninstalls an app from the device under test.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`appId` or `bundleId`|App identifier such as Android app package or iOS bundle ID|string|
|`options?`|Driver-specific uninstall options|unknown|
#### Response
`boolean` - `true` if uninstall was successful, otherwise `false`
### isAppInstalled
```
POST /session/:sessionId/appium/device/app_installed
```
Determines if an app is installed on the device under test.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`appId` or `bundleId`|App identifier such as Android app package or iOS bundle ID|string|
#### Response
`boolean` - `true` if app is installed, otherwise `false`
### hideKeyboard
```
POST /session/:sessionId/appium/device/hide_keyboard
```
Attempts to hide the virtual keyboard on the device under test.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`key?`|Text of a key to use to hide the keyboard|string|
|`keyCode?`|Key code to trigger to hide the keyboard|string|
|`keyName?`|Name of a key to use to hide the keyboard|string|
|`strategy?`|Driver-specific name of a hiding strategy to follow|string|
#### Response
`boolean` - `true` if the operation was successful, otherwise `false`. Note that some platforms
may never return a `false` value.
### isKeyboardShown
```
GET /session/:sessionId/appium/device/is_keyboard_shown
```
Determines if the virtual keyboard is shown on the device under test.
#### Response
`boolean` - `true` if the keyboard is shown, otherwise `false`
### pushFile
```
POST /session/:sessionId/appium/device/push_file
```
Pushes data to a file on the device under test.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`data`|Base64-encoded data to be written to the file|string|
|`path`|Remote path on the device to create the file at|string|
#### Response
`void`
### pullFile
```
POST /session/:sessionId/appium/device/pull_file
```
Retrieves data from a file on the device under test.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`path`|Remote path of the file on the device|string|
#### Response
`string` - the Base64-encoded contents of the file
### pullFolder
```
POST /session/:sessionId/appium/device/pull_folder
```
Retrieves data from a directory on the device under test.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`path`|Remote path of the directory on the device|string|
#### Response
`string` - the Base64-encoded zip file of the directory contents
### getAppiumRotation
```
GET /session/:sessionId/appium/device/rotation
```
Retrieves the current spatial orientation of the device under test.
#### Response
`Rotation` - an object with the following properties:
|Name|Description|Type|
|--|--|--|
|`x`|Degrees by which the device is rotated on its X axis|number|
|`y`|Degrees by which the device is rotated on its Y axis|number|
|`z`|Degrees by which the device is rotated on its Z axis|number|
### setAppiumRotation
```
POST /session/:sessionId/appium/device/rotation
```
Sets the spatial orientation of the device under test.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`x`|Degrees by which the device is rotated on its X axis|number|
|`y`|Degrees by which the device is rotated on its Y axis|number|
|`z`|Degrees by which the device is rotated on its Z axis|number|
#### Response
`null`
### getAppiumOrientation
```
GET /session/:sessionId/appium/device/orientation
```
Retrieves the current orientation of the device under test.
#### Response
`string` - either `PORTRAIT` or `LANDSCAPE`
### setAppiumOrientation
```
POST /session/:sessionId/appium/device/orientation
```
Sets the orientation of the device under test.
#### Parameters
|Name|Description|Type|
|--|--|--|
|`orientation`|New device orientation. Supported values are `PORTRAIT` or `LANDSCAPE`.|string|
#### Response
`null`

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