Compare commits

...
Author SHA1 Message Date
Jonathan Lipps c58f32441d Publish
- appium@2.0.0-beta.43
 - @appium/base-driver@8.7.0
 - @appium/base-plugin@1.10.2
 - @appium/doctor@1.16.25
 - @appium/docutils@0.0.10
 - @appium/fake-driver@4.2.0
 - @appium/fake-plugin@2.1.0
 - @appium/gulp-plugins@7.0.5
 - @appium/images-plugin@1.3.5
 - @appium/support@2.59.5
 - @appium/test-support@1.5.0
 - @appium/types@0.4.0
2022-08-10 07:45:24 -07:00
Jonathan Lipps 325f9900cc chore(appium): don't lint autogenerated docs assets js 2022-08-10 07:42:44 -07:00
Jonathan LippsandChristopher Hiller 337ec3e7ba feat(base-driver,fake-driver,appium): add convenience methods for defining execute script overloads (#17321)
* feat(base-driver,fake-driver,appium): add convenience methods for defining execute script overloads

* Update packages/appium/docs/en/ecosystem/build-drivers.md

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>

* Update packages/appium/docs/en/ecosystem/build-drivers.md

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>

* Update packages/appium/docs/en/ecosystem/build-drivers.md

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>

* Update packages/appium/docs/en/ecosystem/build-drivers.md

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>

* review

* review

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>
2022-08-09 20:47:47 -07:00
Christopher Hiller 888aac85ff fix(support): add missing @appium/types
This package was missing `@appium/types`, which means packages consuming `@appium/support` which _don't_ also consume `appium` in some capacity will have types that won't compile, e.g., `teen_process`.
2022-08-09 15:26:20 -07:00
Christopher Hiller ee0a579ddc chore(gulp-plugins): remove unused babel-eslint 2022-08-09 10:49:44 -07:00
Christopher Hiller 8d6ffe0932 fix(support): path to APPIUM_HOME must always be absolute
Closes #17338
2022-08-09 10:49:32 -07:00
Christopher Hiller d4b983328a feat(appium,base-driver,fake-driver,fake-plugin,test-support,types): updateServer receives cliArgs param
This PR passes a `cliArgs` parameter to the static method `updateServer` of drivers and plugins so they can take action on the server configuration based on the content of the arguments.

Note that `cliArgs` is a misnomer, because these args can also come from configuration files.

Closes #17304
2022-08-08 14:00:58 -07:00
renovate[bot] ce7b4520a4 chore(): update dependency @types/chai to v4.3.3 2022-08-08 11:54:58 +00:00
Christopher Hiller dc4835f293 fix(appium): fix busted config file normalization algorithm
I'm not sure _what_ happened here other than "the types weren't strict enough" otherwise I would have noticed this earlier.  Anyway; the check to see if we should dig into the config object to normalize the keys was getting passed _something_ but that _something_ wasn't anything it expected.

As a result, I needed to update some tests which assumed `readConfigFile()` resolved w/ an identity w/r/t the config file itself.  It doesn't give the config file back verbatim any longer; the result will be normalized to camel-case keys (or whatever the `appiumCliDest` property is, if it exists)
2022-08-04 15:38:52 -07:00
Christopher Hiller dc730e7307 chore(): ignore local_appium_home in wallaby tests 2022-08-04 15:38:52 -07:00
Christopher Hiller ec79486df0 chore(types): enable ESM interop by default
for stuff that is type-checked but not part of the actual build. this was driving me nuts, sorry.
2022-08-04 15:38:52 -07:00
ian zhang b5ea03ae85 docs: Update Edit URL and Fix typo of MJSONWP (#17315)
As branch 2.0 won't there any more , just replace with master as latest resource
2022-08-04 14:10:51 -07:00
Jonathan Lipps 3c6633eaa1 docs(appium): restore config developer docs (#17312) 2022-08-03 16:56:08 -07:00
Jonathan LippsandChristopher Hiller bf53db9fac docs(appium): reorganize migration doc info (#17311)
* docs(appium): reorganize migration doc info so that appropriate bits are in their own docs

* Update packages/appium/docs/en/ecosystem/build-drivers.md

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>

* Update packages/appium/docs/en/ecosystem/build-drivers.md

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>

* Update packages/appium/docs/en/guides/caps.md

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>

* Update packages/appium/docs/en/guides/caps.md

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>

* Update packages/appium/docs/en/guides/config.md

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>

* Update packages/appium/docs/en/guides/config.md

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>

* Update packages/appium/docs/en/guides/config.md

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>

* Update packages/appium/docs/en/guides/config.md

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>

* Update packages/appium/docs/en/guides/config.md

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>

* Update packages/appium/docs/en/guides/migrating-1-to-2.md

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>

* add header for extensions

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>
2022-08-03 15:45:01 -07:00
Jonathan Lipps fd57ff03a4 docs(appium): actually fix link to new docs 2022-08-03 13:13:14 -07:00
Jonathan Lipps 167fdb18f7 docs(appium): fix link to new docs in old docs dir 2022-08-03 13:12:48 -07:00
Jonathan LippsandKazuaki Matsuo 50964e0690 docs(appium): migrate the migration docs and fix urls (#17306)
* docs(appium): migrate the migration docs and fix urls

* Update packages/appium/docs/en/guides/migrating-1-to-2.md

Co-authored-by: Kazuaki Matsuo <fly.49.89.over@gmail.com>

* docs(appium): migrate the migration docs and fix urls

Co-authored-by: Kazuaki Matsuo <fly.49.89.over@gmail.com>
2022-08-03 11:46:48 -07:00
renovate[bot] a2385f08d5 chore(images-plugin): update dependency lru-cache to v7.13.2 2022-08-03 13:39:58 +00:00
63 changed files with 1462 additions and 199 deletions
+1
View File
@@ -7,3 +7,4 @@ sample-code
**/*.d.ts
**/build-fixtures/**
**/*.ts
packages/appium/docs/**/assets/**
+1 -1
View File
@@ -36,7 +36,7 @@ module.exports = (wallaby) => {
'!**/local_appium_home/**',
],
testFramework: 'mocha',
tests: ['./packages/*/test/unit/**/*.spec.js'],
tests: ['./packages/*/test/unit/**/*.spec.js', '!**/local_appium_home/**'],
workers: {
restart: true,
},
+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).
Appium 2.x 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.
+71 -109
View File
@@ -42,7 +42,7 @@
"@babel/register": "7.18.9",
"@babel/runtime": "7.18.9",
"@colors/colors": "1.5.0",
"@types/chai": "4.3.1",
"@types/chai": "4.3.3",
"@types/chai-as-promised": "7.1.5",
"@types/mocha": "9.1.1",
"@types/node": "16.11.47",
@@ -7133,9 +7133,10 @@
}
},
"node_modules/@types/chai": {
"version": "4.3.1",
"dev": true,
"license": "MIT"
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz",
"integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==",
"dev": true
},
"node_modules/@types/chai-as-promised": {
"version": "7.1.5",
@@ -8396,31 +8397,6 @@
"form-data": "^4.0.0"
}
},
"node_modules/babel-eslint": {
"version": "10.1.0",
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.0.0",
"@babel/parser": "^7.7.0",
"@babel/traverse": "^7.7.0",
"@babel/types": "^7.7.0",
"eslint-visitor-keys": "^1.0.0",
"resolve": "^1.12.0"
},
"engines": {
"node": ">=6"
},
"peerDependencies": {
"eslint": ">= 4.12.1"
}
},
"node_modules/babel-eslint/node_modules/eslint-visitor-keys": {
"version": "1.3.0",
"license": "Apache-2.0",
"engines": {
"node": ">=4"
}
},
"node_modules/babel-plugin-dynamic-import-node": {
"version": "2.3.3",
"license": "MIT",
@@ -17741,9 +17717,9 @@
}
},
"node_modules/lru-cache": {
"version": "7.13.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.13.1.tgz",
"integrity": "sha512-CHqbAq7NFlW3RSnoWXLJBxCWaZVBrfa9UEHId2M3AW8iEBurbqduNexEUCGc3SHc6iCYXNJCDi903LajSVAEPQ==",
"version": "7.13.2",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.13.2.tgz",
"integrity": "sha512-VJL3nIpA79TodY/ctmZEfhASgqekbT574/c4j3jn4bKXbSCnTTCH/KltZyvL2GlV+tGSMtsWyem8DCX7qKTMBA==",
"engines": {
"node": ">=12"
}
@@ -25941,17 +25917,17 @@
}
},
"packages/appium": {
"version": "2.0.0-beta.41",
"version": "2.0.0-beta.42",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
"@appium/base-driver": "^8.6.0",
"@appium/base-plugin": "^1.10.0",
"@appium/docutils": "^0.0.8",
"@appium/schema": "^0.0.8",
"@appium/support": "^2.59.3",
"@appium/test-support": "^1.4.0",
"@appium/types": "^0.3.0",
"@appium/base-driver": "^8.6.1",
"@appium/base-plugin": "^1.10.1",
"@appium/docutils": "^0.0.9",
"@appium/schema": "^0.0.9",
"@appium/support": "^2.59.4",
"@appium/test-support": "^1.4.1",
"@appium/types": "^0.3.1",
"@babel/runtime": "7.18.9",
"@sidvind/better-ajv-errors": "2.0.0",
"@types/argparse": "2.0.10",
@@ -26054,10 +26030,10 @@
},
"packages/base-driver": {
"name": "@appium/base-driver",
"version": "8.6.0",
"version": "8.6.1",
"license": "Apache-2.0",
"dependencies": {
"@appium/support": "^2.59.3",
"@appium/support": "^2.59.4",
"@babel/runtime": "7.18.9",
"@colors/colors": "1.5.0",
"@types/async-lock": "1.1.5",
@@ -26074,7 +26050,7 @@
"express": "4.18.1",
"http-status-codes": "2.2.0",
"lodash": "4.17.21",
"lru-cache": "7.13.1",
"lru-cache": "7.13.2",
"method-override": "3.0.0",
"morgan": "1.10.0",
"serve-favicon": "2.5.0",
@@ -26089,10 +26065,10 @@
},
"packages/base-plugin": {
"name": "@appium/base-plugin",
"version": "1.10.0",
"version": "1.10.1",
"license": "Apache-2.0",
"dependencies": {
"@appium/support": "^2.59.3"
"@appium/support": "^2.59.4"
},
"engines": {
"node": ">=14",
@@ -26101,10 +26077,10 @@
},
"packages/doctor": {
"name": "@appium/doctor",
"version": "1.16.23",
"version": "1.16.24",
"license": "Apache-2.0",
"dependencies": {
"@appium/support": "^2.59.3",
"@appium/support": "^2.59.4",
"@babel/runtime": "7.18.9",
"@colors/colors": "1.5.0",
"@types/bluebird": "3.5.36",
@@ -26232,10 +26208,10 @@
},
"packages/docutils": {
"name": "@appium/docutils",
"version": "0.0.8",
"version": "0.0.9",
"license": "Apache-2.0",
"dependencies": {
"@appium/support": "^2.59.3",
"@appium/support": "^2.59.4",
"@babel/runtime": "7.18.9",
"docdash": "1.2.0",
"jsdoc": "3.6.11",
@@ -26250,7 +26226,7 @@
},
"packages/eslint-config-appium": {
"name": "@appium/eslint-config-appium",
"version": "6.0.3",
"version": "6.0.4",
"license": "Apache-2.0",
"engines": {
"node": ">=14",
@@ -26268,7 +26244,7 @@
},
"packages/execute-driver-plugin": {
"name": "@appium/execute-driver-plugin",
"version": "2.0.3",
"version": "2.0.4",
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "7.18.9",
@@ -26289,7 +26265,7 @@
},
"packages/fake-driver": {
"name": "@appium/fake-driver",
"version": "4.0.2",
"version": "4.1.0",
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "7.18.9",
@@ -26314,11 +26290,11 @@
},
"packages/fake-plugin": {
"name": "@appium/fake-plugin",
"version": "2.0.4",
"version": "2.0.5",
"license": "Apache-2.0",
"dependencies": {
"@appium/base-plugin": "^1.10.0",
"@appium/support": "^2.59.3",
"@appium/base-plugin": "^1.10.1",
"@appium/support": "^2.59.4",
"@babel/runtime": "7.18.9",
"@types/bluebird": "3.5.36",
"bluebird": "3.7.2",
@@ -26335,10 +26311,10 @@
},
"packages/gulp-plugins": {
"name": "@appium/gulp-plugins",
"version": "7.0.3",
"version": "7.0.4",
"license": "Apache-2.0",
"dependencies": {
"@appium/eslint-config-appium": "^6.0.3",
"@appium/eslint-config-appium": "^6.0.4",
"@babel/core": "7.18.10",
"@babel/eslint-parser": "7.18.9",
"@babel/plugin-transform-runtime": "7.18.10",
@@ -26351,7 +26327,6 @@
"@types/through2": "2.0.36",
"ansi-red": "0.1.1",
"axios": "0.27.2",
"babel-eslint": "10.1.0",
"babel-plugin-istanbul": "6.1.1",
"babel-plugin-source-map-support": "2.2.0",
"bluebird": "3.7.2",
@@ -26401,12 +26376,12 @@
},
"packages/images-plugin": {
"name": "@appium/images-plugin",
"version": "1.3.3",
"version": "1.3.4",
"license": "Apache-2.0",
"dependencies": {
"@appium/opencv": "^1.0.10",
"@appium/opencv": "^1.0.11",
"@babel/runtime": "7.18.9",
"lru-cache": "7.13.1",
"lru-cache": "7.13.2",
"source-map-support": "0.5.21"
},
"engines": {
@@ -26419,7 +26394,7 @@
},
"packages/opencv": {
"name": "@appium/opencv",
"version": "1.0.10",
"version": "1.0.11",
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "7.18.9",
@@ -26437,7 +26412,7 @@
},
"packages/relaxed-caps-plugin": {
"name": "@appium/relaxed-caps-plugin",
"version": "1.0.0-beta.10",
"version": "1.0.0-beta.11",
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "7.18.9",
@@ -26454,7 +26429,7 @@
},
"packages/schema": {
"name": "@appium/schema",
"version": "0.0.8",
"version": "0.0.9",
"license": "Apache-2.0",
"dependencies": {
"@types/json-schema": "7.0.11",
@@ -26468,9 +26443,10 @@
},
"packages/support": {
"name": "@appium/support",
"version": "2.59.3",
"version": "2.59.4",
"license": "Apache-2.0",
"dependencies": {
"@appium/types": "0.3.1",
"@babel/runtime": "7.18.9",
"@colors/colors": "1.5.0",
"@types/archiver": "5.3.1",
@@ -26536,7 +26512,7 @@
},
"packages/test-support": {
"name": "@appium/test-support",
"version": "1.4.0",
"version": "1.4.1",
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "7.18.9",
@@ -26565,10 +26541,10 @@
},
"packages/types": {
"name": "@appium/types",
"version": "0.3.0",
"version": "0.3.1",
"license": "Apache-2.0",
"dependencies": {
"@appium/schema": "^0.0.8",
"@appium/schema": "^0.0.9",
"@types/express": "4.17.13",
"@types/npmlog": "4.1.4",
"@wdio/types": "7.20.7",
@@ -26581,7 +26557,7 @@
},
"packages/universal-xml-plugin": {
"name": "@appium/universal-xml-plugin",
"version": "1.0.0-beta.12",
"version": "1.0.0-beta.13",
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "7.18.9",
@@ -26621,7 +26597,7 @@
"@appium/base-driver": {
"version": "file:packages/base-driver",
"requires": {
"@appium/support": "^2.59.3",
"@appium/support": "^2.59.4",
"@babel/runtime": "7.18.9",
"@colors/colors": "1.5.0",
"@types/async-lock": "1.1.5",
@@ -26638,7 +26614,7 @@
"express": "4.18.1",
"http-status-codes": "2.2.0",
"lodash": "4.17.21",
"lru-cache": "7.13.1",
"lru-cache": "7.13.2",
"method-override": "3.0.0",
"morgan": "1.10.0",
"serve-favicon": "2.5.0",
@@ -26650,13 +26626,13 @@
"@appium/base-plugin": {
"version": "file:packages/base-plugin",
"requires": {
"@appium/support": "^2.59.3"
"@appium/support": "^2.59.4"
}
},
"@appium/doctor": {
"version": "file:packages/doctor",
"requires": {
"@appium/support": "^2.59.3",
"@appium/support": "^2.59.4",
"@babel/runtime": "7.18.9",
"@colors/colors": "1.5.0",
"@types/bluebird": "3.5.36",
@@ -26743,7 +26719,7 @@
"@appium/docutils": {
"version": "file:packages/docutils",
"requires": {
"@appium/support": "^2.59.3",
"@appium/support": "^2.59.4",
"@babel/runtime": "7.18.9",
"docdash": "1.2.0",
"jsdoc": "3.6.11",
@@ -26784,8 +26760,8 @@
"@appium/fake-plugin": {
"version": "file:packages/fake-plugin",
"requires": {
"@appium/base-plugin": "^1.10.0",
"@appium/support": "^2.59.3",
"@appium/base-plugin": "^1.10.1",
"@appium/support": "^2.59.4",
"@babel/runtime": "7.18.9",
"@types/bluebird": "3.5.36",
"bluebird": "3.7.2",
@@ -26796,7 +26772,7 @@
"@appium/gulp-plugins": {
"version": "file:packages/gulp-plugins",
"requires": {
"@appium/eslint-config-appium": "^6.0.3",
"@appium/eslint-config-appium": "^6.0.4",
"@babel/core": "7.18.10",
"@babel/eslint-parser": "7.18.9",
"@babel/plugin-transform-runtime": "7.18.10",
@@ -26809,7 +26785,6 @@
"@types/through2": "2.0.36",
"ansi-red": "0.1.1",
"axios": "0.27.2",
"babel-eslint": "10.1.0",
"babel-plugin-istanbul": "6.1.1",
"babel-plugin-source-map-support": "2.2.0",
"bluebird": "3.7.2",
@@ -26853,9 +26828,9 @@
"@appium/images-plugin": {
"version": "file:packages/images-plugin",
"requires": {
"@appium/opencv": "^1.0.10",
"@appium/opencv": "^1.0.11",
"@babel/runtime": "7.18.9",
"lru-cache": "7.13.1",
"lru-cache": "7.13.2",
"source-map-support": "0.5.21"
}
},
@@ -26890,6 +26865,7 @@
"@appium/support": {
"version": "file:packages/support",
"requires": {
"@appium/types": "0.3.1",
"@babel/runtime": "7.18.9",
"@colors/colors": "1.5.0",
"@types/archiver": "5.3.1",
@@ -26968,7 +26944,7 @@
"@appium/types": {
"version": "file:packages/types",
"requires": {
"@appium/schema": "^0.0.8",
"@appium/schema": "^0.0.9",
"@types/express": "4.17.13",
"@types/npmlog": "4.1.4",
"@wdio/types": "7.20.7",
@@ -32171,7 +32147,9 @@
}
},
"@types/chai": {
"version": "4.3.1",
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz",
"integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==",
"dev": true
},
"@types/chai-as-promised": {
@@ -32717,13 +32695,13 @@
"appium": {
"version": "file:packages/appium",
"requires": {
"@appium/base-driver": "^8.6.0",
"@appium/base-plugin": "^1.10.0",
"@appium/docutils": "^0.0.8",
"@appium/schema": "^0.0.8",
"@appium/support": "^2.59.3",
"@appium/test-support": "^1.4.0",
"@appium/types": "^0.3.0",
"@appium/base-driver": "^8.6.1",
"@appium/base-plugin": "^1.10.1",
"@appium/docutils": "^0.0.9",
"@appium/schema": "^0.0.9",
"@appium/support": "^2.59.4",
"@appium/test-support": "^1.4.1",
"@appium/types": "^0.3.1",
"@babel/runtime": "7.18.9",
"@sidvind/better-ajv-errors": "2.0.0",
"@types/argparse": "2.0.10",
@@ -32739,7 +32717,7 @@
"asyncbox": "2.9.2",
"axios": "0.27.2",
"bluebird": "3.7.2",
"cross-env": "*",
"cross-env": "7.0.3",
"find-up": "5.0.0",
"lilconfig": "2.0.6",
"lodash": "4.17.21",
@@ -33126,22 +33104,6 @@
"form-data": "^4.0.0"
}
},
"babel-eslint": {
"version": "10.1.0",
"requires": {
"@babel/code-frame": "^7.0.0",
"@babel/parser": "^7.7.0",
"@babel/traverse": "^7.7.0",
"@babel/types": "^7.7.0",
"eslint-visitor-keys": "^1.0.0",
"resolve": "^1.12.0"
},
"dependencies": {
"eslint-visitor-keys": {
"version": "1.3.0"
}
}
},
"babel-plugin-dynamic-import-node": {
"version": "2.3.3",
"requires": {
@@ -39358,9 +39320,9 @@
"version": "2.0.0"
},
"lru-cache": {
"version": "7.13.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.13.1.tgz",
"integrity": "sha512-CHqbAq7NFlW3RSnoWXLJBxCWaZVBrfa9UEHId2M3AW8iEBurbqduNexEUCGc3SHc6iCYXNJCDi903LajSVAEPQ=="
"version": "7.13.2",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.13.2.tgz",
"integrity": "sha512-VJL3nIpA79TodY/ctmZEfhASgqekbT574/c4j3jn4bKXbSCnTTCH/KltZyvL2GlV+tGSMtsWyem8DCX7qKTMBA=="
},
"lru-queue": {
"version": "0.1.0",
+1 -1
View File
@@ -109,7 +109,7 @@
"@babel/register": "7.18.9",
"@babel/runtime": "7.18.9",
"@colors/colors": "1.5.0",
"@types/chai": "4.3.1",
"@types/chai": "4.3.3",
"@types/chai-as-promised": "7.1.5",
"@types/mocha": "9.1.1",
"@types/node": "16.11.47",
+17
View File
@@ -3,6 +3,23 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.0.0-beta.43](https://github.com/appium/appium/compare/appium@2.0.0-beta.42...appium@2.0.0-beta.43) (2022-08-10)
### Bug Fixes
* **appium:** fix busted config file normalization algorithm ([dc4835f](https://github.com/appium/appium/commit/dc4835f293f371c36873801a0060bb22eead2cc0))
### Features
* **appium,base-driver,fake-driver,fake-plugin,test-support,types:** updateServer receives cliArgs param ([d4b9833](https://github.com/appium/appium/commit/d4b983328af21d1e5c27a91e438e7934eb152ab1)), closes [#17304](https://github.com/appium/appium/issues/17304)
* **base-driver,fake-driver,appium:** add convenience methods for defining execute script overloads ([#17321](https://github.com/appium/appium/issues/17321)) ([337ec3e](https://github.com/appium/appium/commit/337ec3e7ba216dd6f8cdc88143ecaa4c75f5d266))
# [2.0.0-beta.42](https://github.com/appium/appium/compare/appium@2.0.0-beta.41...appium@2.0.0-beta.42) (2022-08-03)
@@ -0,0 +1,451 @@
---
title: Appium's Config System
---
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
for Appium contributors, but will also explain the system's fundamental features.
## Reading a Config File
A config file is a JSON, JavaScript, or YAML file which can be validated against a schema. By
default, this file will be named `.appiumrc.{json,js,yaml,yml}` and should be in the root of the
project which depends upon `appium`. Other filenames and locations are supported via the `--config
<file>` flag. For obvious reasons, the `config` argument is disallowed within config files.
In lieu of a separate file, configuration can be embedded in a project's `package.json` using the
`appiumConfig` property, e.g.,:
```json
{
"appiumConfig": {
"server": {
"port": 12345
}
}
}
```
When an Appium server is started via the `appium` executable, the `init` function in `lib/main.js`
will call into `lib/config-file.js` to load and/or search for a configuration file and in
`package.json`.
!!! note
It is not an error if configuration isn't found!
The [`lilconfig`](https://npm.im/lilconfig) package provides the search & load functionality; refer
to its documentation for more information about the search paths. Additionally, Appium provides
support for config files written in YAML via the package [`yaml`](https://npm.im/yaml).
If a config file is found and successfully [validated](#validation), the result will be merged with
a set of defaults and any additionall CLI arguments. CLI arguments have precedence over config
files, and config files have precedence over defaults.
## Validation
The same system is used for _both_ validation of config files _and_ command-line arguments.
The package [`ajv`](https://npm.im/ajv) provides validation. Of course, to make `ajv` validate
anything, it must be provided a _schema_.
The _base_ schema is a [JSON Schema
Draft-7](https://json-schema.org/draft/2020-12/json-schema-core.html)-compliant object exported by
`lib/schema/appium-config-schema.js`. This schema defines configuration _native to Appium_, and
only concerns its behavior as a _server_; it does not define configuration for any other
functionality (e.g., the `plugin` or `driver` subcommands).
!!! warning
Note that this file is the _base_ schema; this will become painfully relevant.
This file is is _not_ a JSON file, because a) JSON is painful to work with for humans, b) is
especially reviled by @jlipps, and c) `ajv` accepts objects, not JSON files.
It is more straightforward to explain how config files are validated, so we'll start there.
### Validating Config Files
When a config file is found (`lib/config-file.js`), it will call the `validate` function exported
from `lib/schema/schema.js` with the contents of the config file. In turn, this asks `ajv` to
validate the data against the schema that Appium has provided it.
If the config file is invalid, errors will be generated to be displayed to the user. Finally, the
`init` function will detect these errors, display them, and the process will exit.
I hope that made sense, because this is the easy part.
### Validating CLI Arguments
As mentioned earlier, the same system is used for validating both config files and CLI arguments.
Totally not judging, but Appium uses [`argparse`](https://npm.im/argparse) for its CLI argument
parsing. This package, and others like it, provides an API to define the arguments a command-line
Node.js script accepts, and will ultimately return an object representation of the user-supplied
arguments.
Just as the schema defines what's allowed in a config file, it also defines what's allowed on the
command-line.
#### Defining CLI Arguments via Schema
CLI arguments must be _defined_ before their values can be validated.
A JSON schema isn't a natural fit for defining CLI args--it needs some grease to make it work--but
it's close enough that we can do so with an adapter and some custom metadata.
In `lib/cli/parser.js`, there's a wrapper around `argparse`'s `ArgumentParser`; it's called (wait
for it)... `ArgParser`. The wrapper exists because we're doing some custom things with `argparse`,
but is has nothing to do with the schema directly.
An `ArgParser` instance is created and its `parseArgs()` method is called with the raw CLI
arguments. The definition of the accepted arguments comes from `lib/cli/args.js` in part--here, all
of the arguments _not_ intended for use with the `server` subcommand are hard-coded (e.g., the
`driver` subcommand and _its_ subcommands). `args.js` also contains a function `getServerArgs()`,
which in turn calls into `toParserArgs` in `lib/schema/cli-args.js`. `lib/schema/cli-args.js` can
be considered the "adapter" layer between `argparse` and the schema.
`toParserArgs` uses the `flattenSchema` function exported by `lib/schema/schema.js`, which
"squashes" the schema into a key/value representation. Then, `toParserArgs` iterates over each
key/value pair and "converts" it into a suitable `ArgumentOption` object for final handoff to
`ArgParser`.
This adapter (`cli-args.js`) is where most of the mess is hidden; let's explore this rat's nest
a bit further.
##### CLI & Schema Incongruities
The conversion algorithm (see function `subSchemaToArgDef` in `lib/schema/cli-args.js`) is mostly
just hacks and special cases neatly packed into a function. Things that don't cleanly map from
`argparse` to a JSON schema include, but are not limited to:
- A schema cannot natively express "store the value of `--foo=<value>` in a property called `bar`" in a schema (this corresponds to the `ArgumentOption['dest']` prop).
- A schema cannot natively express aliases; e.g., `--verbose` can also be `-v`
- A schema `enum` is not restricted to multiple types, but `argparse`'s equivalent `ArgumentOption['choices']` prop _is_
- A schema does not know about `argparse`'s concept of "actions" (note that Appium is not currently using custom actions--though it did, and it could again).
- `argparse` has no native type for `email`, `hostname`, `ipv4`, `uri` etc., and the schema does
- Schema validation only _validates_, it does not perform translation, transformation, or coercion (mostly). `argparse` allows this.
- Schemas allow the `null` type, for whatever reason. Ever pass `null` on the CLI?
- `argparse` does not understand anything other than primitives; no objects, arrays, etc., and certainly not arrays of a particular type.
All of the above cases and others are handled by the adapter.
!!! warning
Some decisions made in the adapter were arrived at via coin toss. If you are curious about why
something is the way it is, it's likely that it had to do _something_.
Let's look more closely at handling types.
#### Argument Types via `ajv`
While `argparse` allows consumers, via its API, to define the _type_ of various arguments (e.g.,
a string, number, boolean flag, etc.), Appium mostly avoids these built-in types. _Why is that?_
Well:
1. We already know the type of an argument, because we've defined it in a schema.
2. `ajv` provides validation against a schema.
3. A schema allows for greater expression of types, allowed values, etc., than `argparse` can provide natively.
4. The expressiveness of a schema allows for better error messaging.
To that end, the adapter eschews `argparse`'s built-in types (see allowed string values of
`ArgumentOption['type']`) and instead abuses the ability to provide a _function_ as a `type`. The
exception is _boolean_ flags, which do not have a `type`, but rather `action: 'store_true'`. The
world may never know why.
##### Types as Functions
When a `type` is a function, the function performs both validation _and_ coercion (if necessary).
So what are these functions?
> Note: `type` is _omitted_ (and thus _not_ a function) from the `ArgumentOption` if the property
> type is `boolean`, and is instead provided an `action` property of `store_true`. Yes, this is
> weird. No, I don't know why.
Well... it depends upon the schema. But generally speaking, we create a _pipeline_ of functions,
each corresponding to a keyword in the schema. Let's take the example of the `port` argument. In
lieu of asking the OS which ports the `appium`-running user can bind to, this argument is expected
to be an integer between 1 and 65535. This turns out to be two functions which we combine into
a pipeline:
1. Convert the value to an integer, if possible. Because _every value in `process.argv` is a string_, we must coerce if we want a number.
2. Use `ajv` to validate the integer against the schema for `port`. A schema lets us define a range via the `minimum` and `maximum` keywords. Read more about how this works in
Much like the config file validation, if errors are detected, Appium nicely tells the end-user and
the process exits w/ some help text.
For other arguments which are naturally of non-primitive types, things are not so straightforward.
##### Transformers
Remember how `argparse` doesn't understand arrays? What if the most ergonomic way to express
a value is, in fact, an array?
Well, Appium can't accept an array on the CLI, even though it can accept one in the config file.
But Appium _can_ accept a comma-delimited string (a CSV "line"). Or a string filepath referring to
a file which _contains_ a delimited list. Either way: by the time the value gets out of the
argument parser, it should be an array.
And as mentioned above, the native facilities of a JSON schema cannot express this. However, it's
possible to define a _custom keyword_ which Appium can then detect and handle accordingly. So
that's what Appium does.
In this case, a custom keyword `appiumCliTransformer` is registered with `ajv`. The value of
`appiumCliTransformer` (at the time of this writing) can be `csv` or `json`. In the base schema
file, `appium-config-schema.js`, Appium uses `appiumCliTransformer: 'csv'` if this behavior is
desired.
!!! note
Any property defined in the schema having type `array` will _automatically_ uses the `csv`
transformer. Likewise, a property having type `object` will use the `json` transformer. It's
conceivable that `array` may want to use the `json` transformer, but otherwise, the presence of
the `appiumCliTransformer` keyword on an `array`-or-`object`-typed property is not stricly
necessary.
The adapter (remember the adapter?) creates a pipeline function including a special "CSV
transformer" (transformers are defined in `lib/schema/cli-transformers.js`), and uses this function
as the `type` property of the `ArgumentOption` passed into `argparse`. In this case, the `type:
'array'` in the schema is ignored.
!!! note
The config file doesn't _need_ to perform any complex transformation of values, because it
naturally allows Appium to define exactly what it expects. So Appium does no post-processing of
config file values.
Properties that do not need this special treatment use `ajv` directly for validation. How this
works requires some explanation, so that's next.
#### Validation of Individual Arguments via `ajv`
When we think of a JSON schema, we tend to think, "I have this JSON file and I want to validate it
against the schema". That's valid, and in fact Appium does just that with config files! However,
Appium does not do this when validating arguments.
!!! note
During implementation, I was tempted to mash all of the arguments together into
a config-file-like data structure and then validate it all at once. I think that would have
been _possible_, but since an object full of CLI arguments is a flat key/value structure and
the schema is not, this seemed like trouble.
Instead, Appium validates a value against a specific property _within_ the schema. To do this, it
maintains a mapping between a CLI argument definition and its corresponding property. The mapping
itself is a `Map` with a unique identifier for the argument as the key, and an `ArgSpec`
(`lib/schema/arg-spec.js`) object as the value.
An `ArgSpec` object stores the following metadata:
| Property Name | Description |
| --------------- | ------------------------------------------------------------------------------------- |
| `name` | Canonical name of the argument, corresponding to the property name in the schema. |
| `extType?` | `driver` or `plugin`, if appropriate |
| `extName?` | Extension name, if appropriate |
| `ref` | Computed `$id` of the property in the schema |
| `arg` | Argument as accepted on CLI, without leading dashes |
| `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-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
an `ArgSpec` for the argument. It creates a function which calls `validate(value, ref)` (in
`lib/schema/schema.js`) where `value` is whatever the user provided, and `ref` is the `ref`
property of the `ArgSpec`. The concept is that `ajv` can validate using _any_ `ref` it knows about;
each property in a schema can be referenced by this `ref` whether it's defined or not. To help
visualize, if a schema is:
```json
{
"$id": "my-schema.json",
"type": "object",
"properties": {
"foo": {
"type": "number"
}
}
}
```
The `ref` of `foo` would be `my-schema.json#/properties/foo`. Assuming our `Ajv` instance knows
about this `my-schema.json`, then we can call its `getSchema(ref)` method (which has a `schema`
property, but is a misnomer nonetheless) to get a validation function; `validate(value, ref)` in
`schema.js` calls this validation function.
!!! note
The schema spec says a schema author can supply an explicit `$id` keyword to override this;
it's unsupported by Appium at this time. If needed, extension authors must carefully use `$ref`
without custom `$id`s. It's highly unlikely an extension would have a schema so complicated as
to need this, however; Appium itself doesn't even use `$ref` to define its own properties!
Next, let's take a look at how Appium loads schemas. This actually happens _before_ any argument
validation.
## Schema Loading
Let's ignore extensions for a moment, and start with the base schema.
When something first imports the `lib/schema/schema.js` module, an instance of an `AppiumSchema` is
created. This is a singleton, and its methods are exported from the module (all of which are bound
to the instance).
The constructor does very little; it instantiates an `Ajv` instance and configures it with Appium's
[custom keywords](#custom-keyword-reference) and adds support for the `format` keyword via the
[ajv-formats](https://npm.im/ajv-formats) module.
Otherwise, the `AppiumSchema` instance does not interact with the `Ajv` instance until its
`finalize()` method (exported as `finalizeSchema()`) is called. When this method is called, we're
saying "we are not going to add any more schemas; go ahead and create `ArgSpec` objects and
register schemas with `ajv`".
When does finalization happen? Well:
1. When the `appium` executable begins, it _checks for and configures extensions_ (hand-wave) in `APPIUM_HOME`.
2. Only then does it start to think about arguments--it instantiates an `ArgParser`, which (as you'll recall) runs the adapter to convert the schema to arguments.
3. _Finalization happens here_--when creating the parser. Appium need the schema(s) to be registered with `ajv` in order to create validation functions for arguments.
4. Thereafter, Appium parses the arguments with the `ArgParser`.
5. Finally, decides what to do with the returned object.
Without extensions, `finalize()` still knows about the Appium base schema
(`appium-config-schema.js`), and just registers that. However, step 1. above is doing a _lot of
work_, so let's look at how extensions come into play.
## Extension Support
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 2.0 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.
Now, by providing a schema for its options, a driver or plugin can register CLI arguments and
config file schemas with Appium.
To register a schema, an extension must provide the `appium.schema` property in its `package.json`.
The value may be a schema or a path to a schema. If the latter, the schema should be JSON or
a CommonJS module (ESM not supported at this time, nor is YAML).
For any property in this schema, the property will appear as a CLI argument of the form
`--<extension-type>-<extension-name>-<property-name>`. For example, if the `fake` driver provides
a property `foo`, the argument will be `--driver-fake-foo`, and will show in `appium server --help`
like any other CLI argument.
The corresponding property in a config file would be
`server.<extension-type>.<extension-name>.<property-name>`, e.g.:
```json
{
"server": {
"driver": {
"fake": {
"foo": "bar"
}
}
}
}
```
The naming convention described above avoids problems of one extension type having a name conflict
with a different extension type.
!!! note
While an extension can provide aliases via `appiumCliAliases`, "short" flags are disallowed,
since all arguments from extensions are prefixed with `--<extension-type>-<extension-name>-`.
The extension name and argument name will be kebab-cased for the CLI, according to [Lodash's
rules](https://lodash.com/docs/4.17.15#kebabCase) around kebab-casing.
The schema object will look much like Appium's base schema, but it will only have top-level
properties (nested properties are currently unsupported). Example:
```json
{
"title": "my rad schema for the cowabunga driver",
"type": "object",
"properties": {
"fizz": {
"type": "string",
"default": "buzz",
"$comment": "corresponds to CLI --driver-cowabunga-fizz"
}
}
}
```
As written in a user's config file, this would be the `server.driver.cowabunga.fizz` property.
When extensions are loaded, the `schema` property is verified and the schema is registered with the
`AppiumSchema` (it is _not_ registered with `Ajv` until `finalize()` is called).
During finalization, each registered schema is added to the `Ajv` instance. The schema is assigned
an `$id` based on the extension type and name (which overrides whatever the extension provides, if
anything). Schemas are also forced to disallowed unknown arguments via the `additionalProperties:
false` keyword.
Behind the scenes, the base schema has `driver` and `plugin` properties which are objects. When
finalized, a property is added to each--corresponding to an extension name--and the value of this
property is a reference to the `$id` of a property in the extension schema. For example, the
`server.driver` property will look like this:
```json
{
"driver": {
"cowabunga": {
"$ref": "driver-cowabunga.json"
}
}
}
```
This is why we call it the "base" schema--it is _mutated_ when extensions provide schemas. The
extension schemas are kept separately, but the _references_ are added to the schema before it's
ultimately added to `ajv`. This works because an `Ajv` instance understands references _from_ any
schema it knows about _to_ any schema it knows about.
!!! note
This makes it impossible to provide a complete static schema for Appium _and_ the installed
extensions (as of Nov 5 2021). A static `.json` schema _is_ generated from the base (via a Gulp
task), but it does not contain any extension schemas. The static schema also has uses beyond
Appium; e.g., IDEs can provide contextual error-checking of config files this way. Let's solve
this?
Just like how we look up the reference ID of a particular argument in the base schema, validation
of arguments from extensions happens the exact same way. If the `cowabunga` driver has the schema
ID `driver-cowabunga.json`, then the `fizz` property can be referenced from any schema registered
with `ajv` via `driver-cowabunga.json#/properties/fizz`. "Base" schema arguments begin with
`appium.json#properties/` instead.
## Development Environment Support
During the flow of development, a couple extra tasks have been automated to maintain the base
schema:
- As a post-transpilation step, a `lib/appium-config.schema.json` gets generated from
- `lib/schema/appium-config-schema.js` (in addition to its CJS counterpart generated by Babel).
- This file is under version control. It ends up being _copied_ to
- `build/lib/appium-config.schema.json` in this step. A pre-commit hook (see
- `scripts/generate-schema-declarations.js` in the root monorepo) generates
- a `types/appium-config-schema.d.ts` from the above JSON file. The types in `types/types.d.ts`
- depend upon this file. This file is under version control.
## Custom Keyword Reference
Keywords are defined in `lib/schema/keywords.js`.
- `appiumCliAliases`: allows a schema to express aliases (e.g., a CLI argument can be `--verbose` or `-v`). This is an array of strings. Strings shorter than three (3) characters will begin with a single dash (`-`) instead of a double-dash (`--`). Note that any argument provided by an extension will begin with a double-dash, because these are required to have the `--<extension-type>-<extension-name>-` prefix.
- `appiumCliDest`: allows a schema to specify a custom property name in the post-`argprase` arguments objects. If not set, this becomes a camelCased string.
- `appiumCliDescription`: allows a schema to override the description of the argument when displayed on the command-line. This is useful paired with `appiumCliTransformer` (or `array`/`object`-typed properties), since there's a substantial difference between what a CLI-using user can provide vs. what a config-file-using user can provide.
- `appiumCliTransformer`: currently a choice between `csv` and `json`. These are custom functions which post-process a value. They are not used when loading & validating config files, but the idea should be that they result in the same object you'd get if you used whatever the config file wanted (e.g., an array of strings). `csv` is for comma-delimited strings and CSV files; `json` is for raw JSON strings and `.json` files.
- `appiumCliIgnore`: If `true`, do not support this property on the CLI.
- `appiumDeprecated`: If `true`, the property is considered "deprecated", and will be displayed as such to the user (e.g., in the `--help` output). Note the JSON Schema draft-2019-09 introduces a new keyword `deprecated` which we should use instead if upgrading to this metaschema. When doing so, `appiumDeprecated` should itself be marked as `deprecated`.
@@ -2,4 +2,22 @@
title: Contributing to Appium
---
This section of Appium's documentation is for those who are interested in contributing to Appium's
development. It contains developer overviews, guides, and notes. Use the navigation menu to find
a specific topic. All the information in these guides assumes in-depth familiarity with Appium
already.
!!! warning
Developer information may not be kept up to date as frequently as user-facing information, or
it may be most relevant in its current form on the online repository, not in this published
version. Always be sure to check the repo or discuss with maintainers. We're always happy to
help new contributors get started!
## Ways to Contribute
TODO
## The Appium Development Process
TODO
@@ -390,11 +390,56 @@ You can add custom CLI args if you want your driver to receive data from the com
Appium server is started (for example, ports that a server administrator should set that should not
be passed in as capabilities.
To do this you define a `schema` field within the `appium` field in `package.json`, pointing to
a JS or JSON file defining an argument schema. (See the schema in `fake-driver`, for example).
Arguments you define there will be available as a `--driver-<name>-<arg-name>` flag on the command
line. If you define `my-arg` in the schema, for example, and if your driver's name is `awesome`,
then users will be able to set your arg via `--driver-awesome-my-arg`.
To define CLI arguments (or configuration properties) for the Appium server, your extension must provide a _schema_. In
the `appium` property of your extension's `package.json`, add a `schema` property. This will either
a) be a schema itself, or b) be a path to a schema file.
The rules for these schemas:
- Schemas must conform to [JSON Schema Draft-07](https://ajv.js.org/json-schema.html#draft-07).
- If the `schema` property is a path to a schema file, the file must be in JSON or JS (CommonJS) format.
- Custom `$id` values are unsupported. To use `$ref`, provide a value relative to the schema root, e.g., `/properties/foo`.
- Known values of the `format` keyword are likely supported, but various other keywords may be unsupported. If you find a keyword that is unsupported which you need to use, please [ask for support](https://github.com/appium/appium/issues/new) or send a PR!
- The schema must be of type `object` (`{"type": "object"}`), containing the arguments in a `properties` keyword. Nested properties are unsupported.
Example:
```json
{
"type": "object",
"properties": {
"test-web-server-port": {
"type": "integer",
"minimum": 1,
"maximum": 65535,
"description": "The port to use for the test web server"
},
"test-web-server-host": {
"type": "string",
"description": "The host to use for the test web server",
"default": "sillyhost"
}
}
}
```
The above schema defines two properties which can be set via CLI argument or configuration file. If
this extension is a _driver_ and its name is "horace", the CLI args would be
`--driver-horace-test-web-server-port` and `--driver-horace-test-web-server-host`, respectively.
Alternatively, a user could provide a configuration file containing:
```json
{
"server": {
"driver": {
"horace": {
"test-web-server-port": 1234,
"test-web-server-host": "localhorse"
}
}
}
}
```
### Add driver scripts
@@ -492,7 +537,7 @@ behaviours that don't map to any of the existing commands, you can create new co
two ways:
1. Extending the WebDriver protocol and creating client-side plugins to access the extensions
1. Overloading the Execute Script command
1. Overloading the Execute Script command by defining "Execute Methods"
If you want to follow the first path, you can direct Appium to recognize new methods and add them
to its set of allowed HTTP routes and command names. You do this by assigning the `newMethodMap`
@@ -521,37 +566,56 @@ create and release client-side plugins for each language you want to support (di
examples can be found at the relevant client docs).
An alternative to this way of doing things is to overload a command which all WebDriver clients
have access to already: Execute Script. A common driver pattern is to create a magic prefix which
the driver looks for at the beginning of any Execute Script invocation, and if it's present, to
treat the rest of the script string as the name of a custom command to execute. This works in large
part because for most platforms beyond web browsers, executing arbitrary JavaScript isn't a thing
that makes sense.
Let's say you are building a driver for stereo system called `soundz`, and you wanted to create
a command for playing a song by name. You could expose this to your users in such a way that they
call something like:
have access to already: Execute Script. Appium provides some a convenient tool for making this
easy. Let's say you are building a driver for stereo system called `soundz`, and you wanted to
create a command for playing a song by name. You could expose this to your users in such a way that
they call something like:
```js
// webdriverio example
// webdriverio example. Calling webdriverio's `executeScript` command is what trigger's Appium's
// Execute Script command handler
driver.executeScript('soundz: playSong', [{song: 'Stairway to Heaven', artist: 'Led Zeppelin'}]);
```
Then in your driver code you could simply look for `soundz:` at the beginning of your
`execute` override, and do the appropriate thing:
Then in your driver code you can define the static property `executeMethodMap` as a mapping of
script names to methods on your driver. It has the same basic form as `newMethodMap`, described
above. Once `executeMethodMap` is defined, you'll also need to implement the Execute Script command
handler, which according to Appium's routes mapping is called `execute`. The implementation can
call a single helper function, `this.executeMethod`, which takes care of looking at the script and
arguments the user sent in and routing it to the correct custom handler you've defined. Here's an
example:
```js
async execute(script, args) {
if (script === 'soundz: playSong') {
const {song, artist} = args[0];
// play the song based on song and artist details
return;
static executeMethodMap = {
'soundz: playSong', {
command: 'soundzPlaySong',
params: {required: ['song', 'artist'], optional: []},
}
}
// otherwise do the normal thing, or throw errors.NotYetImplementedError if you have nothing to
// do (see the section on WebDriver errors in this guide)
async soundzPlaySong(song, artist) {
// play the song based on song and artist details
}
async execute(script, args) {
return await this.executeMethod(script, args);
}
```
A couple notes about this system:
1. The arguments array sent via the call to Execute Script must contain only zero or one element(s). The
first item in the list is considered to be the parameters object for your method. These parameters
will be parsed, validated, and then applied to your overload method in the order specified in
`executeMethodMap` (the order specified in the `required` parameters list, followed by the
`optional` parameters list). I.e., this framework assumes only a single actual argument sent in via
Execute Script (and this argument should be an object with keys/values representing the
parameters your execute method expects).
1. Appium does not automatically implement `execute` (the Execute Script handler) for you. You may
wish, for example, to only call the `executeMethod` helper function when you're not in proxy
mode!
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.
### Implement handling of Appium settings
Appium users can send parameters to your driver via CLI args as well as via capabilities. But these
+134
View File
@@ -3,3 +3,137 @@ title: Capabilities
---
TODO
## Special Notes for Cloud Providers
When managing an Appium cloud, your users may wish to target various independent versions of Appium
drivers and plugins. It is of course up to each service provider how they wish to implement the
discovery, installation, and availability of any official or third party drivers or plugins. _But
the Appium team makes the following recommendations in terms of the *capabilities* service
providers support, for consistency across the industry._ This is a recommendation only, and not
a standard, but adopting it will help users to navigate the increased complexity that working with
Appium 2.0 in a cloud environment may bring.
### Suggested capabilities
In addition to the standard `platformName`, `appium:deviceName`, `appium:automationName`, and
`appium:platformVersion`, we recommend adopting the capability `$cloud:appiumOptions`, where the
label `$cloud` is not meant to be interpreted literally but instead should be replaced by your
vendor prefix (so for HeadSpin it would be `headspin`, Sauce Labs it would be `sauce`, and
BrowserStack it would be `browserstack`, to name just a few examples). The `$cloud:appiumOptions`
capability would itself be a JSON object, with the following internal keys:
| Capability | Used for | Example |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `version` | Designating which version of the Appium server is used to host and manage drivers. If ommitted, behavior left up to the provider, but the recommendation would be to provide the latest official version. | `2.0.0` |
| `automationVersion` | Designating which version of the specified driver should be used. | `1.55.2` |
| `automation` | Designating a custom driver to use (see below for more info). This would override `appium:automationName` and `$cloud:automationVersion` | `{"name": "@org/custom-driver", "source": "github", "package": "custom-driver"}` |
| `plugins` | Designating the list of plugins (and potentially versions of plugins) to be activated (see below for more info). | `["images", "universal-xml"]` |
### Basic example
Appium extensions (drivers and plugins) have a set of properties that specify where they can be
installed from. Cloud providers are obviously under no obligation to provide support for
arbitrarily specified extensions, seeing as these may represent untrusted code running in a managed
environment. In the case where arbitrary extensions are not supported, the `appium:automationName`,
`$cloud:automationVersion`, and `$cloud:appiumPlugins` capabilities should be sufficient. See the
following JSON object representing capabilities for a session:
```json
{
"platformName": "iOS",
"appium:platformVersion": "14.4",
"appium:deviceName": "iPhone 11",
"appium:app": "Some-App.app.zip",
"appium:automationName": "XCUITest",
"$cloud:appiumOptions": {
"appiumVersion": "2.0.0",
"automationVersion": "3.52.0",
"plugins": ["images"]
}
}
```
This set of capabilities requests an Appium 2+ server supporting the XCUITest driver at version
`3.52.0`, and the `images` plugin active. This set is easy for a cloud provider to verify. The
cloud provider can obviously do anything it wants in response to these capabilities, including
downloading Appium and driver and plugin packages on the fly, or erroring out if the versions
requested are not in a supported set, or if the plugin is not supported, etc...
### Basic example with `appium:options`
The previous example still looks a bit disorganized, so of course we also recommend that cloud
providers support the `appium:options` capability as detailed above, which could turn the previous
set of capabilities into the following:
```json
{
"platformName": "iOS",
"appium:options": {
"platformVersion": "14.4",
"deviceName": "iPhone 11",
"app": "Some-App.app.zip",
"automationName": "XCUITest"
},
"$cloud:appiumOptions": {
"appiumVersion": "2.0.0",
"automationVersion": "3.52.0",
"plugins": ["images"]
}
}
```
### Extension objects
Some service providers may wish to dynamically allow access to all of the features of the Appium
2.0 CLI, including downloading arbitrary drivers and plugins. To represent these extensions, we can
define special JSON "extension objects", with the following keys:
- `name`: the name of the extension. This would be an NPM package name (if downloading from NPM), or a git or GitHub spec (if downloading from a git server or GitHub).
- `version`: the version of the extension, e.g., the NPM package version or Git SHA.
- (optional) `source`: a denotation of where the extension can be downloaded from. Recommended to support the following values: `appium`, `npm`, `git`, `github`. Here, `appium` means "Appium's own official list", and should be the default value if this key is not included.
- (optional) `package`: when downloading extensions from git or github, the NPM package name of the extension must also be provided. This is optional for non-git sources.
Since each session is handled by a single driver, the `$cloud:appiumOptions`/`$automation`
capability could be used with an extension object value to denote this driver, for example:
```json
{
"$cloud:appiumOptions": {
"automation": {
"name": "git+https://some-git-host.com/custom-driver-project.git",
"version": "some-git-sha",
"source": "git",
"package": "driver-npm-package-name"
}
}
}
```
And since sessions can handle multiple plugins, each value in the list of `$cloud:appiumPlugins`
could also be an extension object rather than a string, so that specific versions could be
requested:
```json
{
"$cloud:appiumOptions": {
"plugins": [{
"name": "images",
"version": "1.1.0"
}, {
"name": "my-github-org/my-custom-plugin",
"version": "a83f2e",
"source": "github",
"package": "custom-plugin"
}]
}
}
```
These serve as illustrative examples for the recommendations here. Of course it is up to the
service providers to implement the handling of these capabilities at their front end / load
balancer, to perform any error checking, or to actually run any of the `appium driver` or `appium
plugin` CLI commands that support the end user's request. This section is merely a suggestion as to
how service providers might design their user-facing capabilities API in a way which in principle
supports all of the capabilities Appium itself would provide to the end user if they were running
Appium on their own.
+91 -1
View File
@@ -2,4 +2,94 @@
title: The Appium Config File
---
TODO
Instead of passing arguments on the command line to Appium, you may add them to a special config
file. Appium will read values from this config file when it runs. (Please note that CLI arguments
have _precedence_ over configuration files; if a value is set in a config file _and_ via CLI
argument, the CLI argument is preferred.)
## Supported Config File Formats
You can store your config data in the following kinds of files:
- JSON
- YAML
- JS (a JavaScript file exporting a JS object)
- CJS (the same as above; the extension is for common JS)
!!! warning
Note: Configuration files in ESM format are not currently supported.
## Supported Config File Locations
Configuration files can be named anything, but the following filenames will be automatically
discovered and loaded by Appium:
- `.appiumrc.json` (recommended)
- `.appiumrc.yaml`
- `.appiumrc.yml`
- `.appiumrc.js`
- `.appiumrc.cjs`
- `appium.config.js`
- `appium.config.cjs`
- `.appiumrc` (which is considered to be JSON)
Further, _if your project uses Node.js,_ you can use store the configuration inside an `appium` property in your `package.json` and it will be automatically discovered.
### Config File Search
Appium will search _up_ the directory tree from the current working directory for one of these
files. If it reaches the current user's home directory or filesystem root, it will stop looking.
To specify a _custom_ location for your config file, use `appium --config-file /path/to/config/file`.
#### Configuration File Format
First, you might want to look at some examples:
- [Appium Configuration - JSON](https://github.com/appium/appium/blob/master/packages/appium/sample-code/appium.config.sample.json)
- [Appium Configuration - YAML](https://github.com/appium/appium/blob/master/packages/appium/sample-code/appium.config.sample.yaml)
- [Appium Configuration - JS](https://github.com/appium/appium/blob/master/packages/appium/sample-code/appium.config.sample.js)
A description of the format is available, as well:
- [Appium Configuration File JSON Schema](https://github.com/appium/appium/blob/master/packages/schema/lib/appium-config.schema.json)
- [TypeScript declarations for Appium Configuration](https://github.com/appium/appium/blob/master/packages/types/lib/config.ts)
To describe in words, the config file will have a root `server` property, and all arguments are
child properties. For certain properties which must be supplied on the command-line as comma-delimited lists, JSON strings, and/or external filepaths, these instead will be of their "native" type. For example,
`--use-plugins <value>` needs `<value>` to be comma-delimited string or path to a delimited file.
However, the config file just wants an array, e.g.,:
```json
{
"server": {
"use-plugins": ["my-plugin", "some-other-plugin"]
}
}
```
## Configuring extensions (drivers and plugins)
For `driver`-and-`plugin`-specific configuration, these live under the `server.driver` and
`server.plugin` properties, respectively. Each driver or plugin will have its own named property,
and the values of any specific configuration it provides are under this. For example:
```json
{
"server": {
"driver": {
"xcuitest": {
"webkit-debug-proxy-port": 5400
}
}
}
}
```
!!! note
The above configuration corresponds to the `--driver-xcuitest-webkit-debug-proxy-port` CLI argument.
All properties are case-sensitive and will be in [kebab-case](https://en.wikipedia.org/wiki/Naming_convention_(programming)#Delimiter-separated_words). For example, `callback-port` is
allowed, but `callbackPort` is not.
@@ -2,4 +2,206 @@
title: Migrating from Appium 1.x to Appium 2.x
---
This document is a guide for those who are using Appium 1.x and wish to migrate to Appium 2.x. It contains a list of breaking changes and how to migrate your environments or test suites to ensure compatibility with Appium 2.0.
## Overview of Appium 2.0
Appium 2.0 is the most major new release of Appium in over 5 years. The changes in Appium 2.0 are _not_ primarily related to changes in automation behaviors for specific platforms. Instead, Appium 2.0 reenvisions Appium as a _platform_ where "drivers" (code projects that introduce support for automation of a given platform) and "plugins" (code projects that allow for overriding, altering, extending, or adding behaviors to Appium) can be easily created and shared.
At the same time, the Appium project is taking the opportunity to remove many old and deprecated bits of functionality.
Together these do introduce a few breaking changes to how Appium is installed, how drivers and various features are managed, and protocol support. These are detailed below.
## Breaking Changes
Have a look at the [Appium 2.0 release notes](https://github.com/appium/appium/releases) for the most comprehensive lists of changes. Here we call out the breaking changes and what you need to do do account for them.
### :bangbang: Installing drivers during setup
When you installed Appium 1.x, all available drivers would be installed at the same time as the main Appium server. This is no longer the case. Simply installing Appium 2.0 (e.g., by `npm install -g appium`), will install the Appium server only, but no drivers. To install drivers, you must instead use the new [Appium extension CLI](../cli/extensions.md). For example, to install the latest versions of the XCUITest and UiAutomator2 drivers, after installing Appium you would run the following commands:
```
appium driver install xcuitest
appium driver install uiautomator2
```
At this point, your drivers are installed and ready. There's a lot more you can do with this CLI so be sure to check out the docs on it.
If you're running in a CI environment or want to install Appium along with some drivers all in one step, you can do so using some special flags during install, for example:
```
npm install --global appium --drivers=xcuitest,uiautomator2
```
This will install Appium and the two drivers for you in one go.
### :bangbang: Chromedriver installation flags
In Appium 1.x it was possible to customize the way Chromedriver was installed (as part of the UiAutomator2 driver for example), using the following command line flags:
* `--chromedriver-skip-install`
* `--chromedriver-version`
* `--chromedriver-cdnurl`
Because Appium 2.0 now installs drivers for you, and because these flags were implemented as NPM config flags, they will no longer work. Instead, use the following environment variables during driver installation:
* `APPIUM_SKIP_CHROMEDRIVER_INSTALL`
* `CHROMEDRIVER_VERSION`
* `CHROMEDRIVER_CDNURL`
For example:
```
APPIUM_SKIP_CHROMEDRIVER_INSTALL=1 appium driver install uiautomator2
```
### :bangbang: Driver-specific command line options
With Appium 1.x, command-line options specific to particular drivers were all hosted on the main Appium server. So, for example, `--chromedriver-executable` was a CLI parameter you could use with Appium to set the location of a specific Chromedriver version for use with, say, the UiAutomator2 driver.
With Appium 2.x, all driver- and platform-specific CLI params have been moved to the drivers themselves. To access them, you'll now need to prepend the argument with the extension type (either `driver` or `plugin`) and the name of the extension. For example, `--chromedriver-executable` becomes `--driver-uiautomator2-chromedriver-executable`.
### :bangbang: Driver-specific automation commands
The definition of certain commands that pertain only to specific drivers has been moved to those
drivers' implementations. For example, `pressKeyCode` is specific to the UiAutomator2 driver and is
now understood only by that driver. In practice, the only breaking change here is the kind of error
you would encounter if the appropriate driver is not installed. Previously, you would get a `501
Not Yet Implemented` error if using a driver that didn't implement the command. Now, you will get
a `404 Not Found` error because if a driver that doesn't know about the command is not active, the
main Appium server will not define the route corresponding to the command.
### :bangbang: Driver updates
In the past, to get updates to your iOS or Android drivers, you'd simply wait for those updates to be rolled into a new release of Appium, and then update your Appium version. With Appium 2.x, the Appium server and the Appium drivers are versioned and released separately. This means that drivers can be on their own release cadence and that you can get driver updates as they happen, rather than waiting for a new Appium server release. The way to check for driver updates is with the CLI:
```bash
appium driver list --updates
```
If any updates are available, you can then run the `update` command for any given driver:
```bash
appium driver update xcuitest
```
To update the Appium server itself, you do the same thing as in the past: `npm install -g appium`. Now, installing new versions of the Appium server will leave your drivers intact, so the whole process will be much more quick.
### :bangbang: Protocol changes
Appium's API is based on the [W3C WebDriver Protocol](https://www.w3.org/TR/webdriver/), and it has supported this protocol for years. Before the W3C WebDriver Protocol was designed as a web standard, several other protocols were used for both Selenium and Appium. These protocols were the "JSONWP" (JSON Wire Protocol) and "MJSONWP" (Mobile JSON Wire Protocol). The W3C Protocol differs from the (M)JSONWP protocols in a few small ways.
Up until Appium 2.0, Appium supported both protocols, so that older Selenium/Appium clients could still communicate with newer Appium servers. Moving forward, support for older protocols will be removed.
### :bangbang: _Capabilities_
One significant difference between old and new protocols is in the format of capabilities. Previously called "desired capabilities", and now called simply "capabilities", there is now a requirement for a so-called "vendor prefix" on any non-standard capabilities. The list of standard capabilities is given in the [WebDriver Protocol spec](https://www.w3.org/TR/webdriver/#capabilities), and includes a few commonly used capabilities such as `browserName` and `platformName`.
These standard capabilities continue to be used as-is. All other capabilities must include a "vendor prefix" in their name. A vendor prefix is a string followed by a colon, such as `appium:`. Most of Appium's capabilities go beyond the standard W3C capabilities and must therefore include vendor prefixes (we recommend that you use `appium:` unless directed otherwise by documentation). For example:
- `appium:app`
- `appium:noReset`
- `appium:deviceName`
This requirement may or may not be a breaking change for your test suites when targeting Appium 2.0. If you're using an updated Appium client, the client will add the `appium:` prefix for you on all necessary capabilities. New versions of the Appium Inspector tool will also do this. Cloud-based Appium providers may also do this. So simply be aware that if you get any messages to the effect that your capabilities lack a vendor prefix, this is how you solve that problem.
On a related note, it will no longer be possible to start Appium sessions using WebDriver clients that don't support the W3C protocol (see below for a comment to this effect for the WD library).
To make everyone's lives a bit easier, we've also introduced the option of wrapping up all Appium-related capabilities into one object capability, `appium:options`. You can bundle together anything that you would normally put an `appium:` prefix on into this one capability. Here's an example (in raw JSON) of how you might start an iOS session on the Safari browser using `appium:options`:
```json
{
"platformName": "iOS",
"browserName": "Safari",
"appium:options": {
"platformVersion": "14.4",
"deviceName": "iPhone 11",
"automationName": "XCUITest"
}
}
```
(Of course, each client will have a different way of creating structured capabilities like `appium:options` or other ones that you might have seen such as `goog:chromeOptions`). NB: capabilities that show up in `appium:options` will overwrite capabilities of the same name that show up at the top level of the object.
For more information on capabilities, have a look at the [Capabilities Guide](caps.md).
### :bangbang: _Removed Commands_
In addition to commands which have been moved to driver implementations, commands which were a part of the old JSON Wire Protocol and not a part of the W3C Protocol are no longer available:
- TODO (these commands are being identified and removed and will be updated here when complete)
If you use a modern Appium or Selenium client, you should no longer have access to these anyway, so any breaking changes should appear on the client side first and foremost.
### :bangbang: Image analysis features moved to plugin
One of the design goals for Appium 2.0 is to migrate non-core features into special extensions called [plugins](../ecosystem/index.md). This allows people to opt into features which require extra time to download or extra system setup. The various image-related features of Appium (image comparison, finding elements by image, etc...) have been moved into an officially supported plugin called [images](https://github.com/appium/appium/tree/master/packages/images-plugin).
If you use these image-related methods, to continue accessing them you will need to do two things.
1. Install the plugin: `appium plugin install images`
2. Ensure you start the Appium server with access to run the plugin by including it in the list of plugins designated on the command line, e.g., `appium --use-plugins=images`
Image-related commands will also be removed on the client side of things, which means you will need to follow the instructions on the plugin README for installing client-side plugins to access these features.
### :bangbang: Execute Driver Script command moved to plugin
If you use the advanced Execute Driver Script feature (which allows you to send in a WebdriverIO script to have it executed completely on the server instead of command-by-command from the client), this functionality has been moved to a plugin. Here's what to do to keep using it:
1. Install the plugin: `appium plugin install execute-driver`
2. Ensure you start the Appium server with access to run the plugin by including it in the list of plugins designated on the command line, e.g., `appium --use-plugins=execute-driver`
### :bangbang: External Files No Longer Supported for `--nodeconfig`, `--default-capabilities`, `--allow-insecure` and `--deny-insecure`
These options can be provided as strings on the command line (a JSON string for `--nodeconfig` and a comma-separated list of strings for `--allow-insecure` and `--deny-insecure`). Arguments provided on the command line will likely need to be quoted or escaped.
The recommended method to provide these options is now via a [configuration file](#tada-configuration-files).
In summary, if you are using a JSON Appium config file, you can simply cut-and-paste the contents of your "nodeconfig" JSON file into the value of the `server.nodeconfig` property. Any CSV-like files you had previously provided for `--allow-insecure` and `--deny-insecure` become the values of the `server.allow-insecure` and `server.deny-insecure` properties in the Appium config files (respectively); both are arrays of strings.
### :bangbang: Old drivers removed
The old iOS and Android (UiAutomator 1) drivers and related tools (e.g., `authorize-ios`) have been removed. They haven't been relevant for many years anyway.
### :warning: Internal packages renamed
Some Appium-internal NPM packages have been renamed (for example, `appium-base-driver` is now `@appium/base-driver`). This is not a breaking change for Appium users, only for people who have built software that directly incorporates Appium's code.
### :warning: "WD" JavaScript client library no longer supported
For many years, some of Appium's authors maintained the [WD](https://github.com/admc/wd) client library. This library has been deprecated and has not been updated for use with the W3C WebDriver protocol. As such, if you're using this library you'll need to move to a more modern one. We recommend [WebdriverIO](https://webdriver.io).
### :warning: Appium Inspector split out from Appium Desktop
The inspecting portion of Appium Desktop has been moved to its own app, Appium Inspector: [github.com/appium/appium-inspector](https://github.com/appium/appium-inspector). It's fully compatible with Appium 2.0 servers. Simply download it and run it on its own. You no longer need the GUI Appium Desktop server to inspect apps. The Appium Desktop server will continue to be supported at its original site: [github.com/appium/appium-desktop](https://github.com/appium/appium-desktop). It will simply no longer bundle the Inspector with it.
You can also now use the Appium Inspector without downloading anything, by visiting the [web version of Appium Inspector](https://inspector.appiumpro.com). Note that to test against local servers, you'll need to start the server with `--allow-cors` so that the browser-based version of Appium Inspector can access your Appium server to start sessions.
## Major New Features
Apart from the breaking changes mentioned above, in this section is a list of some of the major new features you may wish to take advantage of with Appium 2.0.
### Plugins
#### :tada: _Server Plugins_
TODO
#### :tada: _Client Plugins_
TODO
### :tada: Install drivers and plugins from anywhere
TODO
### :tada: Configuration Files
Appium now supports _configuration files_ in addition to command-line arguments. In a nutshell, nearly all arguments which Appium 1.x required to be provided on the CLI are now able to be expressed via a configuration file. Configuration files may be in JSON, JS, or YAML format. See the [Config Guide](config.md) for a full explanation.
## Special Notes for Cloud Providers
The rest of this document has applied to Appium generally, but some of the architectural changes in Appium 2.0 will constitute breaking changes for Appium-related service providers, whether a cloud-based Appium host or an internal service. At the end of the day, the maintainer of the Appium server is responsible for installing and making available the various Appium drivers and plugins that end users may wish to use.
We encourage cloud providers to thoroughly read and understand our [recommendation for cloud
provider capabilities](caps.md#special-notes-for-cloud-providers) in order to support user needs in
an industry-compatible way!
+4 -2
View File
@@ -1,6 +1,6 @@
INHERIT: ./base-mkdocs.yml
site_url: https://appium.github.io/appium/docs/en
edit_uri: edit/2.0/packages/appium/docs/en
edit_uri: edit/master/packages/appium/docs/en
site_description: The Appium automation project documentation
docs_dir: en
@@ -50,6 +50,8 @@ nav:
- ecosystem/build-drivers.md
- ecosystem/build-plugins.md
- ecosystem/build-docs.md
- Contributing: contributing/index.md
- Contributing:
- contributing/index.md
- contributing/config-system.md
- More Appium Resources: resources.md
- Issues: https://github.com/appium/appium/issues
+1 -1
View File
@@ -1,6 +1,6 @@
INHERIT: ./base-mkdocs.yml
site_url: https://appium.github.io/appium/docs/ja
edit_uri: edit/2.0/packages/appium/docs/ja
edit_uri: edit/master/packages/appium/docs/ja
site_description: The Appium automation project documentation
docs_dir: ja
+1 -1
View File
@@ -1,6 +1,6 @@
INHERIT: ./base-mkdocs.yml
site_url: https://appium.github.io/appium/docs/zh
edit_uri: edit/2.0/packages/appium/docs/zh
edit_uri: edit/master/packages/appium/docs/zh
site_description: The Appium automation project documentation
docs_dir: zh
+4 -2
View File
@@ -161,7 +161,9 @@ export function normalizeConfig(config) {
return _.mapValues(mappedObj, (value, property) => {
const nextSection = section ? `${section}.${property}` : property;
return isSchemaTypeObject(value) ? normalize(config, nextSection) : value;
return isSchemaTypeObject(schema.properties?.[property])
? normalize(config, nextSection)
: value;
});
};
@@ -169,7 +171,7 @@ export function normalizeConfig(config) {
* Returns `true` if the schema prop references an object, or if it's an object itself
* @param {import('ajv').SchemaObject|object} schema - Referencing schema object
*/
const isSchemaTypeObject = (schema) => Boolean(schema.properties);
const isSchemaTypeObject = (schema) => Boolean(schema?.properties || schema?.type === 'object');
return normalize(config);
}
+2
View File
@@ -304,6 +304,7 @@ async function main(args) {
const serverUpdaters = getServerUpdaters(driverClasses, pluginClasses);
const extraMethodMap = getExtraMethodMap(driverClasses, pluginClasses);
/** @type {import('@appium/base-driver').ServerOpts} */
const serverOpts = {
routeConfiguringFunction,
port: parsedArgs.port,
@@ -312,6 +313,7 @@ async function main(args) {
basePath: parsedArgs.basePath,
serverUpdaters,
extraMethodMap,
cliArgs: parsedArgs,
};
if (parsedArgs.keepAliveTimeout) {
serverOpts.keepAliveTimeout = parsedArgs.keepAliveTimeout * 1000;
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "appium",
"version": "2.0.0-beta.42",
"version": "2.0.0-beta.43",
"description": "Automation for Apps.",
"keywords": [
"automation",
@@ -61,13 +61,13 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/base-driver": "^8.6.1",
"@appium/base-plugin": "^1.10.1",
"@appium/docutils": "^0.0.9",
"@appium/base-driver": "^8.7.0",
"@appium/base-plugin": "^1.10.2",
"@appium/docutils": "^0.0.10",
"@appium/schema": "^0.0.9",
"@appium/support": "^2.59.4",
"@appium/test-support": "^1.4.1",
"@appium/types": "^0.3.1",
"@appium/support": "^2.59.5",
"@appium/test-support": "^1.5.0",
"@appium/types": "^0.4.0",
"@babel/runtime": "7.18.9",
"@sidvind/better-ajv-errors": "2.0.0",
"@types/argparse": "2.0.10",
@@ -33,7 +33,7 @@ describe('config file behavior', function () {
it('should return a valid config object', async function () {
const result = await readConfigFile(GOOD_FILEPATH);
result.should.deep.equal({
config: require(GOOD_FILEPATH),
config: normalizeConfig(require(GOOD_FILEPATH)),
filepath: GOOD_FILEPATH,
errors: [],
});
@@ -74,7 +74,7 @@ describe('config file behavior', function () {
it('should return a valid config object', async function () {
const result = await readConfigFile(SECURITY_ARRAY_FILEPATH);
result.should.deep.equal({
config: require(SECURITY_ARRAY_FILEPATH),
config: normalizeConfig(require(SECURITY_ARRAY_FILEPATH)),
filepath: SECURITY_ARRAY_FILEPATH,
errors: [],
});
@@ -114,6 +114,14 @@ describe('FakeDriver - via HTTP', function () {
const {data} = await axios.get(`${testServerBaseUrl}/fakedriver`);
data.should.eql({fakedriver: 'fakeResponse'});
});
it('should update the server with cliArgs', async function () {
// we don't need to check the entire object, since it's large, but we can ensure an
// arg got through.
(await axios.post(`http://${TEST_HOST}:${port}/fakedriverCliArgs`)).data.should.have.property(
'appiumHome',
appiumHome
);
});
});
describe('cli args handling for empty args', function () {
+10 -3
View File
@@ -24,7 +24,7 @@ const wdOpts = {
capabilities: W3C_PREFIXED_CAPS,
};
const FAKE_DRIVER_DIR = path.join(PROJECT_ROOT, 'packages', 'fake-driver');
const FAKE_PLUGIN_DIR = path.join(PROJECT_ROOT, 'node_modules', '@appium', 'fake-plugin');
const FAKE_PLUGIN_DIR = path.join(PROJECT_ROOT, 'packages', 'fake-plugin');
describe('FakePlugin', function () {
/** @type {string} */
@@ -150,9 +150,11 @@ describe('FakePlugin', function () {
describe(`with plugin registered via type ${registrationType}`, function () {
/** @type {AppiumServer} */
let server;
/** @type {import('type-fest').LiteralUnion<'all', string>[]} */
let usePlugins;
before(async function () {
// then start server if we need to
const usePlugins = registrationType === 'explicit' ? ['fake', 'p2', 'p3'] : ['all'];
usePlugins = registrationType === 'explicit' ? ['fake', 'p2', 'p3'] : ['all'];
const args = {
appiumHome,
port,
@@ -171,7 +173,12 @@ describe('FakePlugin', function () {
const res = {fake: 'fakeResponse'};
(await axios.post(`http://${TEST_HOST}:${port}/fake`)).data.should.eql(res);
});
it('should update the server with cliArgs', async function () {
const res = usePlugins;
// we don't need to check the entire object, since it's large, but we can ensure an
// arg got through.
(await axios.post(`http://${TEST_HOST}:${port}/cliArgs`)).data.usePlugins.should.eql(res);
});
it('should modify the method map with new commands', async function () {
const driver = await wdio(wdOpts);
const {sessionId} = driver;
+11 -6
View File
@@ -33,6 +33,11 @@ describe('config-file', function () {
*/
let formatErrors;
/**
* @type {import('appium/lib/config-file').normalizeConfig}
*/
let normalizeConfig;
/**
* Mock instance of `lilconfig` containing stubs for
* `lilconfig#search()` and `lilconfig#load`.
@@ -93,7 +98,7 @@ describe('config-file', function () {
// loads the `config-file` module using the lilconfig mock.
// we only mock lilconfig because it'd otherwise be a pain in the rear to test
// searching for config files, and it increases the likelihood that we'd load the wrong file.
({readConfigFile, formatErrors} = rewiremock.proxy(
({readConfigFile, formatErrors, normalizeConfig} = rewiremock.proxy(
() => require('../../lib/config-file'),
mocks
));
@@ -114,19 +119,19 @@ describe('config-file', function () {
it('should support yaml', async function () {
const {config} = await readConfigFile(GOOD_YAML_CONFIG_FILEPATH);
expect(config).to.eql(GOOD_JSON_CONFIG);
expect(config).to.eql(normalizeConfig(GOOD_JSON_CONFIG));
expect(schema.validate).to.have.been.calledOnce;
});
it('should support json', async function () {
const {config} = await readConfigFile(GOOD_JSON_CONFIG_FILEPATH);
expect(config).to.eql(GOOD_JSON_CONFIG);
expect(config).to.eql(normalizeConfig(GOOD_JSON_CONFIG));
expect(schema.validate).to.have.been.calledOnce;
});
it('should support js', async function () {
const {config} = await readConfigFile(GOOD_JS_CONFIG_FILEPATH);
expect(config).to.eql(GOOD_JSON_CONFIG);
expect(config).to.eql(normalizeConfig(GOOD_JSON_CONFIG));
expect(schema.validate).to.have.been.calledOnce;
});
@@ -188,7 +193,7 @@ describe('config-file', function () {
it('should resolve with an object having `config` property and empty array of errors', function () {
expect(result).to.deep.equal({
config: GOOD_JSON_CONFIG,
config: normalizeConfig(GOOD_JSON_CONFIG),
errors: [],
filepath: GOOD_JSON_CONFIG_FILEPATH,
});
@@ -291,7 +296,7 @@ describe('config-file', function () {
it('should resolve with an object having `config` property and empty array of errors', function () {
expect(result).to.deep.equal({
errors: [],
config: GOOD_JSON_CONFIG,
config: normalizeConfig(GOOD_JSON_CONFIG),
filepath: GOOD_JSON_CONFIG_FILEPATH,
});
});
+1 -1
View File
@@ -60,7 +60,7 @@ describe('Config', function () {
{
config: {
// @ts-expect-error
server: {callbackAddress: 'quux'},
server: {'callback-address': 'quux'},
},
},
{port: 1234},
+12
View File
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [8.7.0](https://github.com/appium/appium/compare/@appium/base-driver@8.6.1...@appium/base-driver@8.7.0) (2022-08-10)
### Features
* **appium,base-driver,fake-driver,fake-plugin,test-support,types:** updateServer receives cliArgs param ([d4b9833](https://github.com/appium/appium/commit/d4b983328af21d1e5c27a91e438e7934eb152ab1)), closes [#17304](https://github.com/appium/appium/issues/17304)
* **base-driver,fake-driver,appium:** add convenience methods for defining execute script overloads ([#17321](https://github.com/appium/appium/issues/17321)) ([337ec3e](https://github.com/appium/appium/commit/337ec3e7ba216dd6f8cdc88143ecaa4c75f5d266))
## [8.6.1](https://github.com/appium/appium/compare/@appium/base-driver@8.6.0...@appium/base-driver@8.6.1) (2022-08-03)
@@ -0,0 +1,65 @@
import _ from 'lodash';
import {errors, makeArgs, checkParams} from '../../protocol';
/**
* @param {SessionBase} Base
* @returns {ExecuteBase}
*/
export function ExecuteMixin(Base) {
/**
* @implements {IExecuteCommands}
*/
class ExecuteCommands extends Base {
/**
* @param {string} script
* @param {[Record<string, any>]|[]} protoArgs
*/
async executeMethod(script, protoArgs) {
// the w3c protocol will give us an array of arguments to apply to a javascript function.
// that's not what we're doing. we're going to look for a JS object as the first arg, so we
// can perform validation on it. we'll ignore everything else.
if (!protoArgs || !_.isArray(protoArgs) || protoArgs.length > 1) {
throw new errors.InvalidArgumentError(
`Did not get correct format of arguments for execute method. Expected zero or one ` +
`arguments to execute script and instead received: ${JSON.stringify(protoArgs)}`
);
}
let args = protoArgs[0] ?? {};
if (!_.isPlainObject(args)) {
throw new errors.InvalidArgumentError(
`Did not receive an appropriate execute method parameters object. It needs to be ` +
`deserializable as a plain JS object`
);
}
const Driver = /** @type {DriverClass} */ (this.constructor);
const availableScripts = _.keys(Driver.executeMethodMap);
const commandMetadata = Driver.executeMethodMap[script];
if (!commandMetadata) {
throw new errors.UnsupportedOperationError(
`Unsupported execute method '${script}'. Available methods ` +
`are: ${availableScripts.join(', ')}`
);
}
let argsToApply = [];
if (!commandMetadata.params) {
commandMetadata.params = {required: [], optional: []};
} else {
commandMetadata.params.required ??= [];
commandMetadata.params.optional ??= [];
checkParams(commandMetadata.params, args, null);
}
argsToApply = makeArgs({}, args, commandMetadata.params, null);
return await this[Driver.executeMethodMap[script].command](...argsToApply);
}
}
return ExecuteCommands;
}
/**
* @typedef {import('@appium/types').ExecuteCommands} IExecuteCommands
* @typedef {import('@appium/types').Driver} Driver
* @typedef {import('@appium/types').DriverClass} DriverClass
* @typedef {import('./session').SessionBase} SessionBase
* @typedef {import('../driver').BaseDriverBase<import('@appium/types').TimeoutCommands & import('@appium/types').EventCommands & import('@appium/types').FindCommands & import('@appium/types').LogCommands & import('@appium/types').SettingsCommands & import('@appium/types').SessionCommands & IExecuteCommands>} ExecuteBase
*/
@@ -6,6 +6,7 @@ import {LogMixin} from './log';
import {SessionMixin} from './session';
import {SettingsMixin} from './settings';
import {TimeoutMixin} from './timeout';
import {ExecuteMixin} from './execute';
/**
* Applies all the mixins to the `BaseDriverBase` class.
@@ -19,7 +20,8 @@ export function createBaseDriverClass(Base) {
const WithLogCommands = LogMixin(WithFindCommands);
const WithSettingsCommands = SettingsMixin(WithLogCommands);
const WithSessionCommands = SessionMixin(WithSettingsCommands);
return WithSessionCommands;
const WithExecuteCommands = ExecuteMixin(WithSessionCommands);
return WithExecuteCommands;
}
/**
@@ -27,6 +27,9 @@ class DriverCore {
*/
static baseVersion = BASEDRIVER_VER;
/** @type {ExecuteMethodMap} */
static executeMethodMap = {};
/**
* @type {string?}
*/
@@ -423,6 +426,7 @@ export {DriverCore};
* @typedef {import('@appium/types').W3CCapabilities} W3CCapabilities
* @typedef {import('@appium/types').Driver} Driver
* @typedef {import('@appium/types').Core} Core
* @typedef {import('@appium/types').ExecuteMethodMap} ExecuteMethodMap
* @typedef {import('@appium/types').ServerArgs} ServerArgs
* @typedef {import('@appium/types').EventHistory} EventHistory
* @typedef {import('@appium/types').AppiumLogger} AppiumLogger
+3 -1
View File
@@ -40,6 +40,7 @@ async function server(opts) {
routeConfiguringFunction,
port,
hostname,
cliArgs,
allowCors = true,
basePath = DEFAULT_BASE_PATH,
extraMethodMap = {},
@@ -71,7 +72,7 @@ async function server(opts) {
});
// allow extensions to update the app and http server objects
for (const updater of serverUpdaters) {
await updater(app, appiumServer);
await updater(app, appiumServer, cliArgs);
}
// once all configurations and updaters have been applied, make sure to set up a catchall
@@ -292,6 +293,7 @@ export {server, configureServer, normalizeBasePath};
* @typedef ServerOpts
* @property {RouteConfiguringFunction} routeConfiguringFunction
* @property {number} port
* @property {import('@appium/types').ServerArgs} cliArgs
* @property {string} [hostname]
* @property {boolean} [allowCors]
* @property {string} [basePath]
+4
View File
@@ -37,3 +37,7 @@ export {
// Web socket helpers
export {DEFAULT_WS_PATHNAME_PREFIX} from './express/websocket';
/**
* @typedef {import('./express/server').ServerOpts} ServerOpts
*/
@@ -5,6 +5,8 @@ import {
CREATE_SESSION_COMMAND,
DELETE_SESSION_COMMAND,
GET_STATUS_COMMAND,
makeArgs,
checkParams,
} from './protocol';
import {NO_SESSION_ID_COMMANDS, ALL_COMMANDS, METHOD_MAP, routeToCommandName} from './routes';
import {errors, isErrorType, errorFromMJSONWPStatusCode, errorFromW3CJsonCode} from './errors';
@@ -13,6 +15,8 @@ export {
routeConfiguringFunction,
errors,
isErrorType,
makeArgs,
checkParams,
errorFromMJSONWPStatusCode,
errorFromW3CJsonCode,
ALL_COMMANDS,
@@ -94,7 +94,7 @@ function unwrapParams(paramSets, jsonObj) {
return res;
}
function checkParams(paramSets, jsonObj, protocol) {
export function checkParams(paramSets, jsonObj, protocol) {
let requiredParams = [];
let optionalParams = [];
let receivedParams = _.keys(jsonObj);
@@ -162,7 +162,7 @@ function checkParams(paramSets, jsonObj, protocol) {
* on handling parameters. This method returns an array of arguments which will
* be applied to a command.
*/
function makeArgs(requestParams, jsonObj, payloadParams, protocol) {
export function makeArgs(requestParams, jsonObj, payloadParams, protocol) {
// We want to pass the "url" parameters to the commands in reverse order
// since the command will sometimes want to ignore, say, the sessionId.
// This has the effect of putting sessionId last, which means in JS we can
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/base-driver",
"version": "8.6.1",
"version": "8.7.0",
"description": "Base driver class for Appium drivers",
"keywords": [
"automation",
@@ -45,7 +45,7 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/support": "^2.59.4",
"@appium/support": "^2.59.5",
"@babel/runtime": "7.18.9",
"@colors/colors": "1.5.0",
"@types/async-lock": "1.1.5",
@@ -62,7 +62,7 @@
"express": "4.18.1",
"http-status-codes": "2.2.0",
"lodash": "4.17.21",
"lru-cache": "7.13.1",
"lru-cache": "7.13.2",
"method-override": "3.0.0",
"morgan": "1.10.0",
"serve-favicon": "2.5.0",
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.10.2](https://github.com/appium/appium/compare/@appium/base-plugin@1.10.1...@appium/base-plugin@1.10.2) (2022-08-10)
**Note:** Version bump only for package @appium/base-plugin
## [1.10.1](https://github.com/appium/appium/compare/@appium/base-plugin@1.10.0...@appium/base-plugin@1.10.1) (2022-08-03)
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/base-plugin",
"version": "1.10.1",
"version": "1.10.2",
"description": "The base plugin used to create Appium 2.0 plugins",
"bugs": {
"url": "https://github.com/appium/appium/issues"
@@ -31,7 +31,7 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/support": "^2.59.4"
"@appium/support": "^2.59.5"
},
"engines": {
"node": ">=14",
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.16.25](https://github.com/appium/appium/compare/@appium/doctor@1.16.24...@appium/doctor@1.16.25) (2022-08-10)
**Note:** Version bump only for package @appium/doctor
## [1.16.24](https://github.com/appium/appium/compare/@appium/doctor@1.16.23...@appium/doctor@1.16.24) (2022-08-03)
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/doctor",
"version": "1.16.24",
"version": "1.16.25",
"description": "Test environment for fitness to run Appium",
"keywords": [
"automation",
@@ -49,7 +49,7 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/support": "^2.59.4",
"@appium/support": "^2.59.5",
"@babel/runtime": "7.18.9",
"@colors/colors": "1.5.0",
"@types/bluebird": "3.5.36",
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.0.10](https://github.com/appium/appium/compare/@appium/docutils@0.0.9...@appium/docutils@0.0.10) (2022-08-10)
**Note:** Version bump only for package @appium/docutils
## [0.0.9](https://github.com/appium/appium/compare/@appium/docutils@0.0.8...@appium/docutils@0.0.9) (2022-08-03)
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/docutils",
"version": "0.0.9",
"version": "0.0.10",
"description": "Documentation generation utilities for Appium and related projects",
"keywords": [
"appium",
@@ -41,7 +41,7 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/support": "^2.59.4",
"@appium/support": "^2.59.5",
"@babel/runtime": "7.18.9",
"docdash": "1.2.0",
"jsdoc": "3.6.11",
+12
View File
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [4.2.0](https://github.com/appium/appium/compare/@appium/fake-driver@4.1.0...@appium/fake-driver@4.2.0) (2022-08-10)
### Features
* **appium,base-driver,fake-driver,fake-plugin,test-support,types:** updateServer receives cliArgs param ([d4b9833](https://github.com/appium/appium/commit/d4b983328af21d1e5c27a91e438e7934eb152ab1)), closes [#17304](https://github.com/appium/appium/issues/17304)
* **base-driver,fake-driver,appium:** add convenience methods for defining execute script overloads ([#17321](https://github.com/appium/appium/issues/17321)) ([337ec3e](https://github.com/appium/appium/commit/337ec3e7ba216dd6f8cdc88143ecaa4c75f5d266))
# [4.1.0](https://github.com/appium/appium/compare/@appium/fake-driver@4.0.2...@appium/fake-driver@4.1.0) (2022-08-03)
@@ -69,6 +69,14 @@ commands.getLog = async function getLog(type) {
}
};
commands.execute = async function execute(script, args) {
return await this.executeMethod(script, args);
};
commands.fakeAddition = async function fakeAddition(num1, num2, num3) {
return num1 + num2 + (num3 ?? 0);
};
Object.assign(extensions, commands, helpers);
export {commands, helpers};
export default extensions;
+18 -1
View File
@@ -113,13 +113,30 @@ class FakeDriver extends BaseDriver {
},
};
static executeMethodMap = {
'fake: addition': {
command: 'fakeAddition',
params: {required: ['num1', 'num2'], optional: ['num3']},
},
'fake: getThing': {
command: 'getFakeThing',
},
'fake: setThing': {
command: 'setFakeThing',
params: {required: ['thing']},
},
};
static fakeRoute(req, res) {
res.send(JSON.stringify({fakedriver: 'fakeResponse'}));
}
static async updateServer(expressApp /*, httpServer*/) {
static async updateServer(expressApp, httpServer, cliArgs) {
// eslint-disable-line require-await
expressApp.all('/fakedriver', FakeDriver.fakeRoute);
expressApp.all('/fakedriverCliArgs', (req, res) => {
res.send(JSON.stringify(cliArgs));
});
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/fake-driver",
"version": "4.1.0",
"version": "4.2.0",
"description": "Mock driver used internally by Appium for testing. Ignore",
"keywords": [
"automation",
@@ -106,6 +106,45 @@ function generalTests() {
res[0].type.should.eql('pointer');
res[0].actions.should.have.length(2);
});
it('should get and set a fake thing via execute overloads', async function () {
let thing = await driver.executeScript('fake: getThing', []);
should.not.exist(thing);
await driver.executeScript('fake: setThing', [{thing: 1234}]);
thing = await driver.executeScript('fake: getThing', []);
thing.should.eql(1234);
});
it('should add 2 numbers via execute overloads', async function () {
await driver.executeScript('fake: addition', [{num1: 2, num2: 3}]).should.eventually.eql(5);
await driver
.executeScript('fake: addition', [{num1: 2, num2: 3, num3: 4}])
.should.eventually.eql(9);
});
it('should throw not implemented if an execute overload isnt supported', async function () {
await driver
.executeScript('fake: blarg', [])
.should.be.rejectedWith(/Unsupported execute method/);
});
it('should throw an error if a required overload param is missing', async function () {
await driver
.executeScript('fake: addition', [{num3: 4}])
.should.be.rejectedWith(/Parameters were incorrect/);
});
it('should throw an error if sending in wrong types of params', async function () {
await driver
.executeScript('fake: addition', [4, 5])
.should.be.rejectedWith(/correct format of arg/);
await driver
.executeScript('fake: addition', [4])
.should.be.rejectedWith(/not receive an appropriate execute/);
await driver
.executeScript('fake: addition', [{num1: 2}, {extra: 'bad'}])
.should.be.rejectedWith(/correct format of arg/);
});
});
}
+11
View File
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.1.0](https://github.com/appium/appium/compare/@appium/fake-plugin@2.0.5...@appium/fake-plugin@2.1.0) (2022-08-10)
### Features
* **appium,base-driver,fake-driver,fake-plugin,test-support,types:** updateServer receives cliArgs param ([d4b9833](https://github.com/appium/appium/commit/d4b983328af21d1e5c27a91e438e7934eb152ab1)), closes [#17304](https://github.com/appium/appium/issues/17304)
## [2.0.5](https://github.com/appium/appium/compare/@appium/fake-plugin@2.0.4...@appium/fake-plugin@2.0.5) (2022-08-03)
+4 -1
View File
@@ -40,9 +40,12 @@ class FakePlugin extends BasePlugin {
}
// eslint-disable-next-line no-unused-vars,require-await
static async updateServer(expressApp, httpServer) {
static async updateServer(expressApp, httpServer, cliArgs) {
expressApp.all('/fake', FakePlugin.fakeRoute);
expressApp.all('/unexpected', FakePlugin.unexpectedData);
expressApp.all('/cliArgs', (req, res) => {
res.send(JSON.stringify(cliArgs));
});
}
async getPageSource(next, driver, ...args) {
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/fake-plugin",
"version": "2.0.5",
"version": "2.1.0",
"description": "A fake Appium 2.0 plugin",
"homepage": "https://appium.io",
"bugs": {
@@ -33,8 +33,8 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/base-plugin": "^1.10.1",
"@appium/support": "^2.59.4",
"@appium/base-plugin": "^1.10.2",
"@appium/support": "^2.59.5",
"@babel/runtime": "7.18.9",
"@types/bluebird": "3.5.36",
"bluebird": "3.7.2",
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.0.5](https://github.com/appium/appium/compare/@appium/gulp-plugins@7.0.4...@appium/gulp-plugins@7.0.5) (2022-08-10)
**Note:** Version bump only for package @appium/gulp-plugins
## [7.0.4](https://github.com/appium/appium/compare/@appium/gulp-plugins@7.0.3...@appium/gulp-plugins@7.0.4) (2022-08-03)
+1 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/gulp-plugins",
"version": "7.0.4",
"version": "7.0.5",
"description": "Custom gulp plugins to be used across all appium modules",
"keywords": [
"automation",
@@ -56,7 +56,6 @@
"@types/through2": "2.0.36",
"ansi-red": "0.1.1",
"axios": "0.27.2",
"babel-eslint": "10.1.0",
"babel-plugin-istanbul": "6.1.1",
"babel-plugin-source-map-support": "2.2.0",
"bluebird": "3.7.2",
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.3.5](https://github.com/appium/appium/compare/@appium/images-plugin@1.3.4...@appium/images-plugin@1.3.5) (2022-08-10)
**Note:** Version bump only for package @appium/images-plugin
## [1.3.4](https://github.com/appium/appium/compare/@appium/images-plugin@1.3.3...@appium/images-plugin@1.3.4) (2022-08-03)
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/images-plugin",
"version": "1.3.4",
"version": "1.3.5",
"description": "Plugin for working with images and image elements in Appium",
"keywords": [
"appium",
@@ -39,7 +39,7 @@
"dependencies": {
"@appium/opencv": "^1.0.11",
"@babel/runtime": "7.18.9",
"lru-cache": "7.13.1",
"lru-cache": "7.13.2",
"source-map-support": "0.5.21"
},
"peerDependencies": {
+12
View File
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.59.5](https://github.com/appium/appium/compare/@appium/support@2.59.4...@appium/support@2.59.5) (2022-08-10)
### Bug Fixes
* **support:** add missing @appium/types ([888aac8](https://github.com/appium/appium/commit/888aac85ffcf9974023ad1173ae89ebf0f27d09a))
* **support:** path to APPIUM_HOME must always be absolute ([8d6ffe0](https://github.com/appium/appium/commit/8d6ffe0932fd2aab0dbdf64e483bb906ad626e17)), closes [#17338](https://github.com/appium/appium/issues/17338)
## [2.59.4](https://github.com/appium/appium/compare/@appium/support@2.59.3...@appium/support@2.59.4) (2022-08-03)
+10 -4
View File
@@ -112,6 +112,8 @@ export const readPackageInDir = _.memoize(
* - If `APPIUM_HOME` is set in the environment, use that
* - If we have an `extensions.yaml` in {@linkcode DEFAULT_APPIUM_HOME}, then use that.
* - If we find a `package.json` in or above `cwd` and {@linkcode shouldUseCwdForAppiumHome} returns `true`, then use the directory containing the `package.json`.
*
* All returned paths will be absolute.
*/
export const resolveAppiumHome = _.memoize(
/**
@@ -119,14 +121,14 @@ export const resolveAppiumHome = _.memoize(
* @returns {Promise<string>}
*/
async function _resolveAppiumHome(cwd = process.cwd()) {
if (process.env.APPIUM_HOME) {
return process.env.APPIUM_HOME;
}
if (!path.isAbsolute(cwd)) {
throw new TypeError('`cwd` parameter must be an absolute path');
}
if (process.env.APPIUM_HOME) {
return path.resolve(cwd, process.env.APPIUM_HOME);
}
/** @type {string|undefined} */
let currentPkgDir;
@@ -136,6 +138,10 @@ export const resolveAppiumHome = _.memoize(
// if we can't find a `package.json`, use the default
if (!currentPkgDir) {
return DEFAULT_APPIUM_HOME;
} else {
// it's unclear from the contract of `pkgDir` whether or not it can return a relative path,
// so let's just be defensive.
currentPkgDir = path.resolve(cwd, currentPkgDir);
}
} catch {
// unclear if this can actually happen
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/support",
"version": "2.59.4",
"version": "2.59.5",
"description": "Support libs used across appium packages",
"keywords": [
"automation",
@@ -44,6 +44,7 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/types": "^0.4.0",
"@babel/runtime": "7.18.9",
"@colors/colors": "1.5.0",
"@types/archiver": "5.3.1",
+17 -4
View File
@@ -70,12 +70,25 @@ describe('env', function () {
});
describe('when APPIUM_HOME is set in env', function () {
beforeEach(function () {
process.env.APPIUM_HOME = '/some/path/to/appium';
describe('when APPIUM_HOME is absolute', function () {
beforeEach(function () {
process.env.APPIUM_HOME = '/some/path/to/appium-home';
});
it('should resolve APPIUM_HOME from env', async function () {
await expect(env.resolveAppiumHome()).to.eventually.equal(process.env.APPIUM_HOME);
});
});
it('should resolve APPIUM_HOME from env', async function () {
await expect(env.resolveAppiumHome()).to.eventually.equal(process.env.APPIUM_HOME);
describe('when APPIUM_HOME is relative', function () {
beforeEach(function () {
process.env.APPIUM_HOME = 'some/path/to/appium-home';
});
it('should resolve to an absolute path', async function () {
await expect(env.resolveAppiumHome()).to.eventually.equal(
path.join(process.cwd(), process.env.APPIUM_HOME)
);
});
});
});
+11
View File
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.5.0](https://github.com/appium/appium/compare/@appium/test-support@1.4.1...@appium/test-support@1.5.0) (2022-08-10)
### Features
* **appium,base-driver,fake-driver,fake-plugin,test-support,types:** updateServer receives cliArgs param ([d4b9833](https://github.com/appium/appium/commit/d4b983328af21d1e5c27a91e438e7934eb152ab1)), closes [#17304](https://github.com/appium/appium/issues/17304)
## [1.4.1](https://github.com/appium/appium/compare/@appium/test-support@1.4.0...@appium/test-support@1.4.1) (2022-08-03)
@@ -136,6 +136,8 @@ export function driverE2ETestSuite(DriverClass, defaultCaps = {}) {
routeConfiguringFunction: routeConfiguringFunction(d),
port,
hostname: address,
// @ts-expect-error
cliArgs: {},
});
({startSession, getSession, endSession, newSessionURL, getCommand, postCommand} =
createSessionHelpers(port, address));
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/test-support",
"version": "1.4.1",
"version": "1.5.0",
"description": "A collection of test utilities used across Appium packages",
"keywords": [
"automation",
+12
View File
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [0.4.0](https://github.com/appium/appium/compare/@appium/types@0.3.1...@appium/types@0.4.0) (2022-08-10)
### Features
* **appium,base-driver,fake-driver,fake-plugin,test-support,types:** updateServer receives cliArgs param ([d4b9833](https://github.com/appium/appium/commit/d4b983328af21d1e5c27a91e438e7934eb152ab1)), closes [#17304](https://github.com/appium/appium/issues/17304)
* **base-driver,fake-driver,appium:** add convenience methods for defining execute script overloads ([#17321](https://github.com/appium/appium/issues/17321)) ([337ec3e](https://github.com/appium/appium/commit/337ec3e7ba216dd6f8cdc88143ecaa4c75f5d266))
## [0.3.1](https://github.com/appium/appium/compare/@appium/types@0.3.0...@appium/types@0.3.1) (2022-08-03)
+14
View File
@@ -44,6 +44,19 @@ export interface SessionCommands {
getSession(): Promise<SingularSessionData>;
}
export interface ExecuteCommands {
executeMethod(script: string, args: [Record<string, any>]|[]): Promise<any>;
}
export interface ExecuteMethodDef {
command: string,
params?: {
required?: string[],
optional?: string[],
}
};
export type ExecuteMethodMap = Record<string, ExecuteMethodDef>;
export interface MultiSessionData {
id: string;
capabilities: Capabilities;
@@ -574,6 +587,7 @@ export interface DriverStatic {
baseVersion: string;
updateServer?: UpdateServerCallback;
newMethodMap?: MethodMap<ExternalDriver>;
executeMethodMap: ExecuteMethodMap;
}
/**
+3 -1
View File
@@ -161,8 +161,10 @@ export type ExtensionType = DriverType | PluginType;
*
* @param expressApp - the Express 'app' object used by Appium for route handling
* @param httpServer - the node HTTP server that hosts the app
* @param cliArgs - Arguments from config files, CLI, etc.
*/
export type UpdateServerCallback = (expressApp: Express, httpServer: AppiumServer) => Promise<void>;
export type UpdateServerCallback = (expressApp: Express, httpServer: AppiumServer, cliArgs: ServerArgs) => Promise<void>;
/**
* Possible HTTP methods, as stolen from `axios`.
+1 -1
View File
@@ -1,4 +1,4 @@
import {MethodMap, UpdateServerCallback, Class, AppiumLogger} from '.';
import {MethodMap, UpdateServerCallback, Class, AppiumLogger, PluginType} from '.';
import {Driver, ExternalDriver} from './driver';
/**
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/types",
"version": "0.3.1",
"version": "0.4.0",
"description": "Various type declarations used across Appium",
"keywords": [
"appium",
+3
View File
@@ -1,5 +1,8 @@
{
"files": [],
"compilerOptions": {
"esModuleInterop": true
},
"references": [
{
"path": "packages/schema"