Compare commits

...
Author SHA1 Message Date
Jonathan Lipps 74292e2292 chore: publish
- appium@2.11.2
 - @appium/base-driver@9.11.2
 - @appium/base-plugin@2.2.42
 - @appium/doctor@2.1.9
 - @appium/docutils@1.0.18
 - @appium/driver-test-support@0.6.6
 - @appium/execute-driver-plugin@3.0.32
 - @appium/fake-plugin@3.1.46
 - @appium/images-plugin@3.0.17
 - @appium/logger@1.6.0
 - @appium/opencv@3.0.5
 - @appium/plugin-test-support@0.3.40
 - @appium/strongbox@0.3.3
 - @appium/support@5.1.2
 - @appium/test-support@3.0.46
 - @appium/types@0.21.1
2024-07-10 12:39:13 -07:00
Sudharsan Selvaraj 8ccaf09877 chore(docs): Add FlutterIntegration driver to community supported driver list (#20354) 2024-07-09 17:36:44 +02:00
renovate[bot] d3d77a38df chore(deps): update dependency rimraf to v5.0.9 (#20349)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-09 11:32:48 +02:00
renovate[bot] 0149490522 chore(deps): update eslint-related packages to v7.16.0 (#20350)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-09 11:32:27 +02:00
Mykola Mokhnach 16015de1b5 chore(driver-test-support): Bump chai and chai-as-promised (#20344) 2024-07-08 22:56:16 +02:00
Mykola Mokhnach b7999aed03 chore(types): Deprecate AppiumServerSocket (#20348) 2024-07-08 20:34:04 +02:00
Mykola Mokhnach 1fa8c54765 chore(base-driver): Optimize server close algorithm (#20345) 2024-07-08 14:59:43 +02:00
Mykola Mokhnach 8565209fda chore(execute-driver-plugin): Update wdio resolution (#20346) 2024-07-08 13:29:18 +02:00
Mykola Mokhnach f8819836b5 chore(base-driver): Improve the exception message (#20343) 2024-07-07 09:30:12 +02:00
Mykola Mokhnach ac912606e7 chore(base-driver): Optimize routeToCommandName logic (#20331) 2024-07-07 08:04:26 +02:00
renovate[bot] dcac55711c chore(deps): update dependency rimraf to v5.0.8 2024-07-06 15:32:00 +00:00
renovate[bot] 821ed01ae2 chore(deps): update dependency lerna to v8.1.6 2024-07-06 14:32:03 +00:00
renovate[bot] 62fe09d563 chore(deps): update dependency @types/node to v20.14.10 2024-07-06 09:53:34 +00:00
renovate[bot] 8894b9adf7 fix(types): update dependency type-fest to v4.21.0 (#20335)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-05 13:58:24 +03:00
renovate[bot] 44e423110a fix(appium): update dependency ws to v8.18.0 2024-07-04 18:57:21 +00:00
renovate[bot] 41a18f3b68 chore(deps): update dependency mocha to v10.6.0 2024-07-04 16:22:07 +00:00
renovate[bot] c2f3a618e4 fix(execute-driver-plugin): update dependency webdriverio to v8.39.1 2024-07-04 13:37:24 +00:00
renovate[bot] 5ce3b0c1aa chore(deps): update dependency npm-run-all2 to v6.2.2 2024-07-04 09:17:13 +00:00
renovate[bot] 177dff4f0e fix(doctor): update dependency appium-adb to v12.4.8 2024-07-03 18:40:47 +00:00
Mykola Mokhnach e7665d1cd9 feat(logger): Use LRUCache to manage log history (#20325) 2024-07-03 19:25:21 +02:00
renovate[bot] 34b636082f chore(docutils): update dependency mkdocs-material to v9.5.28 2024-07-03 13:11:18 +00:00
renovate[bot] 06607da92e fix(support): update dependency teen_process to v2.2.0 2024-07-02 16:28:23 +00:00
renovate[bot] 9d6bbdb13e chore(deps): update eslint-related packages to v7.15.0 2024-07-02 13:25:44 +00:00
renovate[bot] 234ad59798 fix(docutils): update dependency typescript to v5.5.3 2024-07-02 10:01:42 +00:00
renovate[bot] fe1b926886 chore(deps): update dependency eslint-plugin-promise to v6.4.0 2024-07-01 11:36:46 +00:00
renovate[bot] 5281f5a01a fix(doctor): update dependency appium-adb to v12.4.6 2024-06-30 13:46:46 +00:00
renovate[bot] 86f843b9e1 fix(support): update dependency teen_process to v2.1.10 2024-06-30 09:48:08 +00:00
renovate[bot] 5226fa897b fix(support): update dependency teen_process to v2.1.7 2024-06-29 12:09:54 +00:00
Jonathan Lipps 19928e9b90 chore: publish
- appium@2.11.1
 - @appium/base-driver@9.11.1
 - @appium/base-plugin@2.2.41
 - @appium/doctor@2.1.8
 - @appium/docutils@1.0.17
 - @appium/driver-test-support@0.6.5
 - @appium/fake-plugin@3.1.45
 - @appium/images-plugin@3.0.16
 - @appium/support@5.1.1
 - @appium/test-support@3.0.45
2024-06-28 16:12:35 -07:00
renovate[bot] e43c7a4dce fix(images-plugin): update dependency lru-cache to v10.3.0 (#20306)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-28 15:59:13 +03:00
renovate[bot] 82e40c1400 fix(driver-test-support): update dependency @types/lodash to v4.17.6 2024-06-28 09:50:07 +00:00
Kazuaki Matsuo f3d959ef91 fix(support): add ? in casae it does not have updateAsyncStorage function deps (#20304) 2024-06-27 23:37:50 -07:00
Jonathan Lipps e8a838417a chore: publish
- appium@2.11.0
 - @appium/base-driver@9.11.0
 - @appium/base-plugin@2.2.40
 - @appium/doctor@2.1.7
 - @appium/docutils@1.0.16
 - @appium/driver-test-support@0.6.4
 - @appium/execute-driver-plugin@3.0.31
 - @appium/fake-plugin@3.1.44
 - @appium/images-plugin@3.0.15
 - @appium/logger@1.5.0
 - @appium/plugin-test-support@0.3.39
 - @appium/support@5.1.0
 - @appium/test-support@3.0.44
 - @appium/types@0.21.0
2024-06-27 12:12:33 -07:00
renovate[bot] 9773a23b26 chore(deps): update dependency mocha to v10.5.2 2024-06-27 09:27:08 +00:00
renovate[bot] cc10b65ee5 chore(deps): update dependency json-schema-to-typescript to v14.1.0 2024-06-26 14:33:41 +00:00
renovate[bot] 530045ec53 chore(deps): update dependency @types/node to v20.14.9 2024-06-26 10:10:08 +00:00
renovate[bot] 8e0fa2c1b3 chore(deps): update eslint-related packages to v7.14.1 2024-06-25 18:27:57 +00:00
renovate[bot] d0d7548576 chore(deps): update dependency mocha to v10.5.1 2024-06-25 15:01:30 +00:00
renovate[bot] c7198b13e4 chore(deps): update dependency lerna to v8.1.5 2024-06-25 10:52:13 +00:00
renovate[bot] 4279cc6cee chore(docutils): update dependency mike to v2.1.2 2024-06-25 06:54:41 +00:00
renovate[bot] a746eefbbb fix(base-driver): update dependency path-to-regexp to v7 (#20279) 2024-06-25 08:50:56 +02:00
renovate[bot] b6de85359d chore(deps): update definitelytyped 2024-06-22 19:32:26 +00:00
Edgars Eglītis f2c8b69608 feat(appium): show extension update info message for newer major versions (#20283)
* feat(appium): add extension update info message if newer major version exists

* chore: add comment
2024-06-22 20:33:09 +03:00
Mykola Mokhnach 87fc50c2af fix(logger): Print an empty message if no arguments are provided (#20284) 2024-06-22 17:21:54 +02:00
Edgars Eglītis f25079354b feat(appium): show spinner during extension uninstall (#20282) 2024-06-22 00:05:43 +03:00
renovate[bot] 189bce88a0 fix(docutils): update dependency typescript to v5.5.2 2024-06-21 19:34:14 +00:00
renovate[bot] 15234bc055 fix(doctor): update dependency appium-adb to v12.4.4 2024-06-21 17:28:47 +00:00
renovate[bot] 073447ae4a fix(support): update dependency @types/uuid to v10 (#20280)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-21 15:51:15 +03:00
renovate[bot] dd070dc51d chore(deps): update dependency @types/node to v20.14.7 2024-06-21 09:48:41 +00:00
Mykola Mokhnach 2882e71631 fix(base-driver): Check if app path is relative earlier (#20276) 2024-06-21 10:55:08 +02:00
Jonathan Lipps c106326169 docs(appium): README logos need to be fully qualified URLs (#20249)
So they should up on NPM OK.
2024-06-20 09:23:56 -07:00
renovate[bot] 5203480df6 chore(deps): update dependency @types/node to v20.14.6 2024-06-20 14:32:36 +00:00
Hans Chan 52ae52a90a docs: fix some deprecated links of w3c and android (#20272) 2024-06-20 12:39:31 +03:00
renovate[bot] d5e5186cb7 fix(support): update dependency glob to v10.4.2 (#20268)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-20 09:30:54 +03:00
renovate[bot] 541246184d fix(support): update dependency teen_process to v2.1.6 2024-06-19 09:25:11 +00:00
renovate[bot] faf9623a65 fix(execute-driver-plugin): update dependency webdriverio to v8.39.0 2024-06-18 20:36:52 +00:00
renovate[bot] bc388db111 fix(support): update dependency teen_process to v2.1.5 2024-06-18 16:58:10 +00:00
renovate[bot] bdea13130c chore(deps): update eslint-related packages to v7.13.1 2024-06-18 12:29:03 +00:00
renovate[bot] cc23c22b60 chore(deps): update dependency @types/node to v20.14.5 2024-06-18 10:06:06 +00:00
kkb912002 f675abc27b feat(appium): Improve context logging (#20250) 2024-06-18 09:55:30 +02:00
renovate[bot] 6fa0ed57ff chore(deps): update dependency tsd to v0.31.1 (#20260)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-18 09:38:13 +03:00
renovate[bot] 57bbb7f46d fix(support): update dependency uuid to v10 (#20236)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-17 22:54:22 +02:00
renovate[bot] d2b24daba0 fix(appium): update dependency ws to v8.17.1 2024-06-17 12:23:23 +00:00
renovate[bot] 14d27fe2a4 chore(docutils): update dependency mkdocs-material to v9.5.27 2024-06-17 09:22:02 +00:00
renovate[bot] 19845531f5 fix(types): update dependency type-fest to v4.20.1 (#20255)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-16 22:21:42 +03:00
Mykola Mokhnach 3cc878d835 chore(appium): Tune logging for the log rules config issues (#20253) 2024-06-13 19:46:33 +02:00
renovate[bot] 4345a40a15 fix(doctor): update dependency appium-adb to v12.4.3 2024-06-13 12:04:45 +00:00
Jonathan Lipps 89e5f7e8db chore: publish
- appium@2.10.3
 - @appium/base-driver@9.10.3
 - @appium/base-plugin@2.2.39
 - @appium/doctor@2.1.6
 - @appium/docutils@1.0.15
 - @appium/driver-test-support@0.6.3
 - @appium/fake-plugin@3.1.43
 - @appium/images-plugin@3.0.14
 - @appium/logger@1.4.2
 - @appium/plugin-test-support@0.3.38
 - @appium/support@5.0.3
 - @appium/test-support@3.0.43
 - @appium/types@0.20.3
2024-06-11 13:02:33 -07:00
Corneliu Duplachi 9469aaef0e fix(logger): use index.d.ts for types instead of index.ts (#20247) 2024-06-11 21:18:52 +02:00
Jonathan Lipps 2b12d5974a chore: publish
- appium@2.10.2
 - @appium/base-driver@9.10.2
 - @appium/base-plugin@2.2.38
 - @appium/doctor@2.1.5
 - @appium/docutils@1.0.14
 - @appium/driver-test-support@0.6.2
 - @appium/fake-plugin@3.1.42
 - @appium/images-plugin@3.0.13
 - @appium/plugin-test-support@0.3.37
 - @appium/schema@0.6.1
 - @appium/support@5.0.2
 - @appium/test-support@3.0.42
 - @appium/types@0.20.2
2024-06-11 12:06:28 -07:00
Jonathan Lipps 45cc948671 fix(schema): edit a comment in order to trigger a publish 2024-06-11 12:05:50 -07:00
180 changed files with 5003 additions and 7259 deletions
+1
View File
@@ -63,5 +63,6 @@ appium.zip
**/build-fixtures/**
*.tsbuildinfo
packages/*/LICENSE
\!packages/*/LICENSE
local_appium_home
*.tgz
+1 -1
View File
@@ -3,7 +3,7 @@
'use strict';
module.exports = {
require: [require.resolve('./test/setup.js')],
require: ['ts-node/register'],
// forbids use of .only() in CI
forbidOnly: Boolean(process.env.CI),
color: true,
+2988 -6722
View File
File diff suppressed because it is too large Load Diff
+17 -20
View File
@@ -65,7 +65,7 @@
"sync-pkgs:license": "sync-monorepo-packages --force --no-package-json --packages=\"!packages/logger\" LICENSE",
"test": "run-s test:quick",
"test:ci": "run-s test:smoke test:unit test:types test:e2e",
"test:e2e": "lerna run --concurrency=2 test:e2e",
"test:e2e": "lerna run test:e2e",
"test:quick": "run-s lint test:unit test:types",
"test:slow": "run-s test:quick test:smoke test:e2e",
"test:smoke": "smoker --all test:smoke",
@@ -86,8 +86,8 @@
"@types/chai": "4.3.16",
"@types/chai-as-promised": "7.1.8",
"@types/diff": "5.2.1",
"@types/mocha": "10.0.6",
"@types/node": "20.14.2",
"@types/mocha": "10.0.7",
"@types/node": "20.14.10",
"@types/semver": "7.5.8",
"@types/sinon": "17.0.3",
"@types/sinon-chai": "3.2.12",
@@ -95,12 +95,11 @@
"@types/teen_process": "2.0.4",
"@types/ws": "8.5.10",
"@types/yargs": "17.0.32",
"@typescript-eslint/eslint-plugin": "7.13.0",
"@typescript-eslint/parser": "7.13.0",
"@typescript-eslint/eslint-plugin": "7.16.0",
"@typescript-eslint/parser": "7.16.0",
"asyncbox": "3.0.0",
"chai": "4.4.1",
"chai-as-promised": "7.1.2",
"chai-webdriverio-async": "3.0.0",
"chai": "5.1.1",
"chai-as-promised": "8.0.0",
"conventional-changelog-conventionalcommits": "7.0.2",
"cpy-cli": "5.0.0",
"eslint": "8.57.0",
@@ -109,33 +108,31 @@
"eslint-import-resolver-typescript": "3.6.1",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-mocha": "10.4.3",
"eslint-plugin-promise": "6.2.0",
"eslint-plugin-promise": "6.4.0",
"fancy-log": "2.0.0",
"finalhandler": "1.2.0",
"get-port": "5.1.1",
"json-schema-to-typescript": "14.0.5",
"lerna": "8.1.3",
"json-schema-to-typescript": "14.1.0",
"lerna": "8.1.6",
"log-symbols": "4.1.0",
"midnight-smoker": "8.0.0",
"mjpeg-consumer": "2.0.0",
"mjpeg-server": "0.3.1",
"mocha": "10.4.0",
"mocha-chai-jest-snapshot": "1.1.4",
"npm-run-all2": "6.2.0",
"mocha": "10.6.0",
"npm-run-all2": "6.2.2",
"prettier": "3.3.2",
"rewiremock": "3.14.5",
"rimraf": "5.0.7",
"rimraf": "5.0.9",
"serve-static": "1.15.0",
"sinon": "18.0.0",
"sinon-chai": "3.7.0",
"sync-monorepo-packages": "1.0.2",
"through2": "4.0.2",
"ts-node": "10.9.2",
"tsd": "0.31.0",
"typescript": "5.4.5",
"tsd": "0.31.1",
"typescript": "5.5.3",
"validate.js": "0.13.1",
"webdriverio": "8.38.2",
"ws": "8.17.0",
"webdriverio": "8.39.1",
"ws": "8.18.0",
"yaml-js": "0.3.1"
},
"engines": {
+59
View File
@@ -3,6 +3,65 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.11.2](https://github.com/appium/appium/compare/appium@2.11.1...appium@2.11.2) (2024-07-10)
### Bug Fixes
* **appium:** update dependency ws to v8.18.0 ([44e4231](https://github.com/appium/appium/commit/44e423110ad6c8bd7d846cc334fafe931fea43f9))
* **execute-driver-plugin:** update dependency webdriverio to v8.39.1 ([c2f3a61](https://github.com/appium/appium/commit/c2f3a618e413c7f21057ba6d9002dc1fe4507e6f))
* **support:** update dependency teen_process to v2.1.10 ([86f843b](https://github.com/appium/appium/commit/86f843b9e1fc56576d7a08bf95838a58971e98b3))
* **support:** update dependency teen_process to v2.1.7 ([5226fa8](https://github.com/appium/appium/commit/5226fa897b90e9fec9be3e79a7d48fc7b4e0016d))
* **support:** update dependency teen_process to v2.2.0 ([06607da](https://github.com/appium/appium/commit/06607da92e93d015747fd6d6d5bdabe1b3ac58d2))
* **types:** update dependency type-fest to v4.21.0 ([#20335](https://github.com/appium/appium/issues/20335)) ([8894b9a](https://github.com/appium/appium/commit/8894b9adf709646108cc8d6426bbb690550609f2))
## [2.11.1](https://github.com/appium/appium/compare/appium@2.11.0...appium@2.11.1) (2024-06-28)
### Bug Fixes
* **images-plugin:** update dependency lru-cache to v10.3.0 ([#20306](https://github.com/appium/appium/issues/20306)) ([e43c7a4](https://github.com/appium/appium/commit/e43c7a4dce1f50fbd4d028cbeac5677422210b20))
## [2.11.0](https://github.com/appium/appium/compare/appium@2.10.3...appium@2.11.0) (2024-06-27)
### Features
* **appium:** Improve context logging ([#20250](https://github.com/appium/appium/issues/20250)) ([f675abc](https://github.com/appium/appium/commit/f675abc27b3e6beac2431cc71afb5fc2c2f70534))
* **appium:** show extension update info message for newer major versions ([#20283](https://github.com/appium/appium/issues/20283)) ([f2c8b69](https://github.com/appium/appium/commit/f2c8b696085ba862553476f23509cac0674a447c))
* **appium:** show spinner during extension uninstall ([#20282](https://github.com/appium/appium/issues/20282)) ([f250793](https://github.com/appium/appium/commit/f25079354bfd646810813ae47244a1e2e962dbfb))
### Bug Fixes
* **appium:** update dependency ws to v8.17.1 ([d2b24da](https://github.com/appium/appium/commit/d2b24daba056373160d680ec5f017b28e9cbde1a))
* **execute-driver-plugin:** update dependency webdriverio to v8.39.0 ([faf9623](https://github.com/appium/appium/commit/faf9623a65868a6330d062076074da7c1c3acb2a))
* **support:** update dependency teen_process to v2.1.5 ([bc388db](https://github.com/appium/appium/commit/bc388db1116f411f4b241105f5feae30418c9a27))
* **support:** update dependency teen_process to v2.1.6 ([5412461](https://github.com/appium/appium/commit/541246184dc7521c825ec1902775e681ea6f0db3))
* **types:** update dependency type-fest to v4.20.1 ([#20255](https://github.com/appium/appium/issues/20255)) ([1984553](https://github.com/appium/appium/commit/19845531f558e2b16dfae807c768e1b9f2cab25d))
## [2.10.3](https://github.com/appium/appium/compare/appium@2.10.2...appium@2.10.3) (2024-06-11)
**Note:** Version bump only for package appium
## [2.10.2](https://github.com/appium/appium/compare/appium@2.10.1...appium@2.10.2) (2024-06-11)
**Note:** Version bump only for package appium
## [2.10.1](https://github.com/appium/appium/compare/appium@2.10.0...appium@2.10.1) (2024-06-11)
**Note:** Version bump only for package appium
@@ -43,6 +43,7 @@ These drivers are not maintained by the Appium team and can be used to target ad
|[Tizen](https://github.com/Samsung/appium-tizen-driver)|`--source=npm appium-tizen-driver`|Android|Native|Community / Samsung|
|[TizenTV](https://github.com/headspinio/appium-tizen-tv-driver)|`--source=npm appium-tizen-tv-driver`|Samsung TV|Web|HeadSpin|
|[Youi](https://github.com/YOU-i-Labs/appium-youiengine-driver)|`--source=npm appium-youiengine-driver`|iOS, Android, macOS, Linux, tvOS|Native|Community / You.i|
|[Flutter Integration](https://github.com/AppiumTestDistribution/appium-flutter-integration-driver)|`--source=npm appium-flutter-integration-driver`|Android, iOS|Native|Community / AppiumTestDistribution|
!!! note
+1 -1
View File
@@ -47,7 +47,7 @@ another project called WebDriver) developed a relatively stable API for browser
Over the years, Selenium worked with various web browser vendors and the [W3C](https://w3c.org)
standards group to turn its API into an official web browser standard, called the [WebDriver
specification](https://w3c.github.io/webdriver/webdriver-spec.html). All the main browsers now
specification](https://w3c.github.io/webdriver/). All the main browsers now
implement automation capabilities inline with the WebDriver spec, without the Selenium team having
to maintain any software that performs actual automation; standards for the win!
+1 -1
View File
@@ -6,7 +6,7 @@ title: Intro to Appium Clients
---
For all the reasons discussed in the [main Overview](./appium.md), Appium is based on the [W3C
WebDriver specification](https://w3c.github.io/webdriver/webdriver-spec.html). This means that
WebDriver specification](https://w3c.github.io/webdriver/). This means that
Appium implements a client-server architecture. The server (consisting of Appium itself along with
any drivers or plugins you are using for automation) is connected to the devices under test, and
is actually responsible for making automation happen on those devices. The client (driven by *you*,
+2 -2
View File
@@ -37,7 +37,7 @@ their WebDriver protocol equivalents.
So let's say I wanted to do something with this empty driver; first I have to decide which
WebDriver command I want to implement. For our example, let's take the [Navigate
To](https://www.w3.org/TR/webdriver1/#navigate-to) WebDriver command. Leave aside for the moment
To](https://w3c.github.io/webdriver/#navigate-to) WebDriver command. Leave aside for the moment
what I want to have the driver *do* when this command is executed. To tell Appium the driver can
handle the command, all we have to do is define a method like this in our driver class:[^1]
@@ -96,7 +96,7 @@ a driver becomes the task of mapping the WebDriver protocol to this underlying A
a set of different underlying APIs--for example, the UiAutomator2 driver relies not only on the
[UiAutomator2](https://developer.android.com/training/testing/other-components/ui-automator)
technology from Google, but also functions only available through
[ADB](https://developer.android.com/studio/command-line/adb), as well as functions only available
[ADB](https://developer.android.com/tools/adb), as well as functions only available
via the Android SDK inside a helper app). Tying it all together into a single, usable, WebDriver
interface is the incredibly useful (but incredibly challenging) art of driver development!
+11 -2
View File
@@ -578,7 +578,9 @@ class ExtensionCliCommand {
return this.config.installedExtensions;
}
const pkgName = extRecord.pkgName;
await npm.uninstallPackage(this.config.appiumHome, pkgName);
await spinWith(this.isJsonOutput, `Uninstalling ${this.type} '${installSpec}'`, async () => {
await npm.uninstallPackage(this.config.appiumHome, pkgName);
});
await this.config.removeExtension(installSpec);
this.log.ok(`Successfully uninstalled ${this.type} '${installSpec}'`.green);
return this.config.installedExtensions;
@@ -639,9 +641,16 @@ class ExtensionCliCommand {
const updateVer = unsafe && update.unsafeUpdate ? update.unsafeUpdate : update.safeUpdate;
await spinWith(
this.isJsonOutput,
`Updating driver '${e}' from ${update.current} to ${updateVer}`,
`Updating ${this.type} '${e}' from ${update.current} to ${updateVer}`,
async () => await this.updateExtension(e, updateVer)
);
// if we're doing a safe update, but an unsafe update is also available, let the user know
if (!unsafe && update.unsafeUpdate) {
const newMajorUpdateMsg = `A newer major version ${update.unsafeUpdate} ` +
`is available for ${this.type} '${e}', which could include breaking changes. ` +
`If you want to apply this update, re-run with --unsafe`;
this.log.info(newMajorUpdateMsg.yellow);
}
updates[e] = {from: update.current, to: updateVer};
} catch (err) {
errors[e] = err;
+27 -14
View File
@@ -142,7 +142,7 @@ function createConsoleTransport(args, logLvl) {
format: format.combine(
formatTimestamp(args),
isLogColorEnabled(args) ? colorizeFormat : stripColorFormat,
format.printf(formatLogLine(args, true))
formatLog(args, true),
),
});
}
@@ -166,7 +166,7 @@ function createFileTransport(args, logLvl) {
format: format.combine(
stripColorFormat,
formatTimestamp(args),
format.printf(formatLogLine(args, false))
formatLog(args, false),
),
});
}
@@ -199,7 +199,7 @@ function createHttpTransport(args, logLvl) {
level: logLvl,
format: format.combine(
stripColorFormat,
format.printf(formatLogLine(args, false))
formatLog(args, false),
),
});
}
@@ -288,22 +288,35 @@ function colorizePrefix(text) {
/**
* @param {ParsedArgs} args
* @param {boolean} targetConsole
* @returns {(info: import('logform').TransformableInfo) => string}
* @returns {import('logform').Format}
*/
function formatLogLine(args, targetConsole) {
return (info) => {
if (['json', 'pretty_json'].includes(args.logFormat)) {
let infoCopy = {...info};
if (targetConsole && !args.logTimestamp) {
delete infoCopy.timestamp;
}
return JSON.stringify(infoCopy, null, args.logFormat === 'pretty_json' ? 2 : undefined);
}
function formatLog(args, targetConsole) {
if (['json', 'pretty_json'].includes(args.logFormat)) {
return format.combine(
format((info) => {
const infoCopy = {...info};
const contextInfo = globalLog.asyncStorage.getStore() ?? {};
if (targetConsole && !args.logTimestamp) {
delete infoCopy.timestamp;
}
if (!_.isEmpty(contextInfo)) {
infoCopy.context = {...contextInfo};
}
return infoCopy;
})(),
format.json({space: args.logFormat === 'pretty_json' ? 2 : undefined}),
);
}
return format.printf((info) => {
if (targetConsole) {
return `${args.logTimestamp ? `${info.timestamp} - ` : ''}${info.message}`;
}
return `${info.timestamp} ${info.message}`;
};
});
}
/**
+6 -2
View File
@@ -249,15 +249,19 @@ async function init(args) {
const {issues, rules} = await logger.unwrap().loadSecureValuesPreprocessingRules(
serverArgs.logFilters,
);
const argToLog = _.truncate(JSON.stringify(serverArgs.logFilters), {
length: 150
});
if (!_.isEmpty(issues)) {
throw new Error(
`The log filtering rules config '${serverArgs.logFilters}' has issues: ` +
`The log filtering rules config ${argToLog} has issues: ` +
JSON.stringify(issues, null, 2),
);
}
if (_.isEmpty(rules)) {
logger.warn(
`Found no log filtering rules in '${serverArgs.logFilters}'. Is that expected?`,
`Found no log filtering rules in the ${argToLog} config. ` +
`Is that expected?`,
);
} else {
// Filtering aims to "hide" these values from the log,
+13 -13
View File
@@ -1,6 +1,6 @@
{
"name": "appium",
"version": "2.10.1",
"version": "2.11.2",
"description": "Automation for Apps.",
"keywords": [
"automation",
@@ -54,18 +54,18 @@
"postinstall": "node ./scripts/autoinstall-extensions.js",
"publish:docs": "cross-env APPIUM_DOCS_PUBLISH=1 npm run build:docs",
"test": "npm run test:unit",
"test:e2e": "mocha -p --timeout 1m --slow 30s \"./test/e2e/**/*.spec.js\"",
"test:e2e": "mocha --timeout 1m --slow 30s \"./test/e2e/**/*.spec.js\"",
"test:smoke": "cross-env APPIUM_HOME=./local_appium_home node ./index.js driver install uiautomator2 && cross-env APPIUM_HOME=./local_appium_home node ./index.js driver list",
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/base-driver": "^9.10.1",
"@appium/base-plugin": "^2.2.37",
"@appium/docutils": "^1.0.13",
"@appium/logger": "^1.4.1",
"@appium/schema": "^0.6.0",
"@appium/support": "^5.0.1",
"@appium/types": "^0.20.1",
"@appium/base-driver": "^9.11.2",
"@appium/base-plugin": "^2.2.42",
"@appium/docutils": "^1.0.18",
"@appium/logger": "^1.6.0",
"@appium/schema": "^0.6.1",
"@appium/support": "^5.1.2",
"@appium/types": "^0.21.1",
"@sidvind/better-ajv-errors": "2.1.3",
"@types/argparse": "2.0.16",
"@types/bluebird": "3.5.42",
@@ -83,17 +83,17 @@
"cross-env": "7.0.3",
"lilconfig": "3.1.2",
"lodash": "4.17.21",
"lru-cache": "10.2.2",
"lru-cache": "10.3.0",
"ora": "5.4.1",
"package-changed": "3.0.0",
"resolve-from": "5.0.0",
"semver": "7.6.2",
"source-map-support": "0.5.21",
"teen_process": "2.1.4",
"type-fest": "4.20.0",
"teen_process": "2.2.0",
"type-fest": "4.21.0",
"winston": "3.13.0",
"wrap-ansi": "7.0.0",
"ws": "8.17.0",
"ws": "8.18.0",
"yaml": "2.4.5"
},
"engines": {
@@ -1,5 +1,5 @@
{
"devDependencies": {
"webdriverio": "8.38.2"
"webdriverio": "8.39.1"
}
}
+7 -2
View File
@@ -10,15 +10,20 @@ import {
runAppiumRaw,
} from './e2e-helpers';
const {expect} = chai;
describe('argument parsing', function () {
/**
* @type {string}
*/
let appiumHome;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
appiumHome = await tempDir.openDir();
});
@@ -16,8 +16,6 @@ import {
import {FAKE_DRIVER_DIR, resolveFixture} from '../helpers';
import {installLocalExtension, runAppiumJson, runAppiumRaw} from './e2e-helpers';
const {expect} = chai;
const TEST_DRIVER_DIR = path.dirname(resolveFixture('test-driver/package.json'));
const TEST_DRIVER_INVALID_PEERS_DIR = path.dirname(
@@ -56,6 +54,7 @@ describe('Driver CLI', function () {
* @type {(args: string[]) => Promise<ExtRecord<DriverType>>}
*/
let runDoctor;
let expect;
async function resetAppiumHome() {
await fs.rimraf(appiumHome);
@@ -63,6 +62,12 @@ describe('Driver CLI', function () {
}
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
appiumHome = await tempDir.openDir();
const run = runAppiumJson(appiumHome);
runInstall = async (args) =>
@@ -5,8 +5,6 @@ import {EXT_SUBCOMMAND_RUN as RUN, PLUGIN_TYPE} from '../../lib/constants';
import {FAKE_PLUGIN_DIR} from '../helpers';
import {installLocalExtension, runAppiumJson} from './e2e-helpers';
const {expect} = chai;
describe('Plugin CLI', function () {
/**
* @type {string}
@@ -17,8 +15,15 @@ describe('Plugin CLI', function () {
* @type {(args: string[]) => Promise<{ output: string, error?: string }>}
*/
let runRun;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
appiumHome = await tempDir.openDir();
const run = runAppiumJson(appiumHome);
runRun = async (args) =>
@@ -22,6 +22,13 @@ describe('config file behavior', function () {
const EXT_PROPS_FILEPATH = resolveConfigFixture('appium-config-ext-good.json');
const LOG_FILTERS_FILEPATH = resolveConfigFixture('appium-config-log-filters.json');
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
beforeEach(function () {
finalizeSchema();
});
@@ -6,6 +6,7 @@ import * as teenProcess from 'teen_process';
describe('Config', function () {
let sandbox;
let should;
beforeEach(function () {
sandbox = createSandbox();
@@ -15,6 +16,13 @@ describe('Config', function () {
sandbox.restore();
});
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
should = chai.should();
});
describe('getGitRev', function () {
it('should get a reasonable git revision', async function () {
let rev = await getGitRev();
+12 -2
View File
@@ -23,8 +23,6 @@ import {
W3C_PREFIXED_CAPS,
} from '../helpers';
const should = chai.should();
/** @type {string} */
let testServerBaseUrl;
@@ -87,8 +85,14 @@ describe('FakeDriver via HTTP', function () {
/** @type {import('sinon').SinonSandbox} */
let sandbox;
let should;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
should = chai.should();
sandbox = createSandbox();
appiumHome = await tempDir.openDir();
wdOpts.port = port = await getTestPort();
@@ -637,8 +641,14 @@ describe('Bidi over SSL', function () {
let certPath = 'certificate.cert';
let keyPath = 'certificate.key';
const capabilities = {...caps, webSocketUrl: true};
let should;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
should = chai.should();
try {
await generateCertificate(certPath, keyPath);
} catch (e) {
+7 -1
View File
@@ -14,7 +14,6 @@ import {FAKE_DRIVER_DIR, resolveFixture} from '../helpers';
import {installLocalExtension, runAppiumJson} from './e2e-helpers';
const {MANIFEST_RELATIVE_PATH} = env;
const {expect} = chai;
const testDriverPath = path.dirname(resolveFixture('test-driver/package.json'));
describe('when Appium is a dependency of the current project', function () {
@@ -26,8 +25,15 @@ describe('when Appium is a dependency of the current project', function () {
let appiumHomePkgPath;
/** @type {string} */
let appiumHome;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
appiumHome = await tempDir.openDir();
});
@@ -10,8 +10,6 @@ import {
import {FAKE_DRIVER_DIR, resolveFixture} from '../helpers';
import {installLocalExtension, runAppiumJson} from './e2e-helpers';
const {expect} = chai;
describe('manifest handling', function () {
/**
* @type {string}
@@ -27,6 +25,7 @@ describe('manifest handling', function () {
* @type {(args?: string[]) => Promise<ExtensionListData>}
*/
let runList;
let expect;
async function resetAppiumHome() {
await fs.rimraf(appiumHome);
@@ -34,6 +33,12 @@ describe('manifest handling', function () {
}
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
appiumHome = await tempDir.openDir();
manifestPath = path.join(appiumHome, CACHE_DIR_RELATIVE_PATH, 'extensions.yaml');
const run = runAppiumJson(appiumHome);
+6 -2
View File
@@ -21,8 +21,6 @@ import {
const FAKE_ARGS = {sillyWebServerPort: 1234, host: 'hey'};
const FAKE_PLUGIN_ARGS = {fake: FAKE_ARGS};
const should = chai.should();
/** @type {import('webdriverio').RemoteOptions} */
const wdOpts = {
hostname: TEST_HOST,
@@ -41,8 +39,14 @@ describe('FakePlugin w/ FakeDriver via HTTP', function () {
let port;
/** @type {string} */
let testServerBaseSessionUrl;
let should;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
should = chai.should();
resetSchema();
appiumHome = await tempDir.openDir();
wdOpts.port = port = await getTestPort();
+7 -2
View File
@@ -5,15 +5,20 @@ import {DRIVER_TYPE} from '../../lib/constants';
import {resolveFixture} from '../helpers';
import {installLocalExtension, runAppium} from './e2e-helpers';
const {expect} = chai;
describe('CLI behavior controlled by schema', function () {
/**
* @type {string}
*/
let appiumHome;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
appiumHome = await tempDir.openDir();
});
+12 -5
View File
@@ -14,8 +14,6 @@ import BasePlugin from '@appium/base-plugin';
const SESSION_ID = '1';
const {expect} = chai;
describe('AppiumDriver', function () {
/** @type {import('sinon').SinonSandbox} */
let sandbox;
@@ -25,6 +23,15 @@ describe('AppiumDriver', function () {
/** @type {MockConfig} */
let MockConfig;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
});
beforeEach(function () {
sandbox = createSandbox();
@@ -64,10 +71,10 @@ describe('AppiumDriver', function () {
// triggers the `log` getter to set `_log`
ad.log;
// now we can stub `_log`, since it exists
sandbox.stub(ad._log, 'debug');
const debugStrub = sandbox.stub(ad._log, 'debug');
// finally, wait for `updateBuildInfo()` to finish up
await promise;
ad._log.debug.should.have.been.calledOnce;
debugStrub.calledOnce.should.be.true;
});
});
@@ -403,7 +410,7 @@ describe('AppiumDriver', function () {
[ArgsPlugin, 'args'],
]);
for (const plugin of appium.createPluginInstances()) {
chai.expect(plugin.cliArgs).to.eql({});
expect(plugin.cliArgs).to.eql({});
}
});
});
@@ -17,6 +17,11 @@ describe('DriverCommand', function () {
let sandbox;
before(async function () {
const chai = await import('chai');
chai.should();
});
beforeEach(async function () {
sandbox = createSandbox();
appiumHome = await tempDir.openDir();
@@ -2,8 +2,6 @@ import {createSandbox} from 'sinon';
import {finalizeSchema, resetSchema, SchemaFinalizationError} from '../../../lib/schema/schema';
import {rewiremock} from '../../helpers';
const expect = chai.expect;
describe('cli/schema-args', function () {
/** @type {import('appium/lib/schema/cli-args').toParserArgs} */
let toParserArgs;
@@ -12,6 +10,15 @@ describe('cli/schema-args', function () {
* @type {sinon.SinonSandbox}
*/
let sandbox;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
});
beforeEach(function () {
sandbox = createSandbox();
@@ -2,10 +2,17 @@ import {createSandbox} from 'sinon';
import {system} from '@appium/support';
import {getPresetDrivers} from '../../../lib/cli/setup-command';
const expect = chai.expect;
describe('SetupCommand', function () {
let sandbox;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
});
beforeEach(function () {
sandbox = createSandbox();
+28 -16
View File
@@ -6,8 +6,6 @@ import YAML from 'yaml';
import * as schema from '../../lib/schema/schema';
import {resolveFixture, rewiremock} from '../helpers';
const expect = chai.expect;
describe('config-file', function () {
const GOOD_YAML_CONFIG_FILEPATH = resolveFixture('config', 'appium-config-good.yaml');
const GOOD_JSON_CONFIG_FILEPATH = resolveFixture('config', 'appium-config-good.json');
@@ -47,8 +45,15 @@ describe('config-file', function () {
let lc;
let mocks;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
before(function () {
// generally called via the CLI parser, this needs to be done manually in tests.
// we don't need to do this before _each_ test, because we're not changing the schema.
// if we did change the schema, this would need to be in `beforeEach()` and `afterEach()`
@@ -120,19 +125,22 @@ describe('config-file', function () {
it('should support yaml', async function () {
const {config} = await readConfigFile(GOOD_YAML_CONFIG_FILEPATH);
expect(config).to.eql(normalizeConfig(GOOD_JSON_CONFIG));
expect(schema.validate).to.have.been.calledOnce;
// @ts-ignore
schema.validate.calledOnce.should.be.true;
});
it('should support json', async function () {
const {config} = await readConfigFile(GOOD_JSON_CONFIG_FILEPATH);
expect(config).to.eql(normalizeConfig(GOOD_JSON_CONFIG));
expect(schema.validate).to.have.been.calledOnce;
// @ts-ignore
schema.validate.calledOnce.should.be.true;
});
it('should support js', async function () {
const {config} = await readConfigFile(GOOD_JS_CONFIG_FILEPATH);
expect(config).to.eql(normalizeConfig(GOOD_JSON_CONFIG));
expect(schema.validate).to.have.been.calledOnce;
// @ts-ignore
schema.validate.calledOnce.should.be.true;
});
describe('when no filepath provided', function () {
@@ -141,12 +149,13 @@ describe('config-file', function () {
});
it('should search for a config file', function () {
expect(lc.search).to.have.been.calledOnce;
expect(schema.validate).to.have.been.calledOnce;
lc.search.calledOnce.should.be.true;
// @ts-ignore
schema.validate.calledOnce.should.be.true;
});
it('should not try to load a config file directly', function () {
expect(lc.load).to.not.have.been.called;
lc.load.called.should.be.false;
});
describe('when no config file is found', function () {
@@ -160,7 +169,8 @@ describe('config-file', function () {
it('should resolve with an empty object', function () {
expect(result).to.be.an('object').that.is.empty;
expect(schema.validate).not.to.have.been.called;
// @ts-ignore
schema.validate.calledOnce.should.be.false;
});
});
@@ -183,7 +193,8 @@ describe('config-file', function () {
describe('when the config file is not empty', function () {
it('should validate the config against a schema', function () {
expect(schema.validate).to.have.been.calledOnceWith(GOOD_JSON_CONFIG);
// @ts-ignore
schema.validate.calledOnceWith(GOOD_JSON_CONFIG).should.be.true;
});
describe('when the config file is valid', function () {
@@ -226,11 +237,11 @@ describe('config-file', function () {
});
it('should not attempt to find a config file', function () {
expect(lc.search).to.not.have.been.called;
lc.search.called.should.be.false;
});
it('should try to load a config file directly', function () {
expect(lc.load).to.have.been.calledOnce;
lc.load.calledOnce.should.be.true;
});
describe('when no config file exists at path', function () {
@@ -285,7 +296,8 @@ describe('config-file', function () {
describe('when the config file is not empty', function () {
it('should validate the config against a schema', function () {
expect(schema.validate).to.have.been.calledOnceWith(GOOD_JSON_CONFIG);
// @ts-ignore
schema.validate.calledOnceWith(GOOD_JSON_CONFIG).should.be.true;
});
describe('when the config file is valid', function () {
@@ -340,12 +352,12 @@ describe('config-file', function () {
it('should call `betterAjvErrors()` with option `json: opts.json`', function () {
// @ts-expect-error
formatErrors([{}], {}, {json: '{"foo": "bar"}'});
expect(mocks['@sidvind/better-ajv-errors']).to.have.been.calledWith(
mocks['@sidvind/better-ajv-errors'].calledWith(
schema.getSchema(),
{},
[{}],
{format: 'cli', json: '{"foo": "bar"}'}
);
).should.be.true;
});
});
});
+12 -5
View File
@@ -23,6 +23,13 @@ describe('Config', function () {
/** @type {sinon.SinonSandbox} */
let sandbox;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
beforeEach(function () {
sandbox = createSandbox();
});
@@ -45,7 +52,7 @@ describe('Config', function () {
it('should log build info to console', async function () {
const config = getBuildInfo();
await showBuildInfo();
log.should.have.been.calledOnce;
log.calledOnce.should.be.true;
log.firstCall.args.should.contain(JSON.stringify(config));
});
});
@@ -64,7 +71,7 @@ describe('Config', function () {
{port: 1234},
{allowCors: false}
);
log.should.have.been.calledWith('Appium Configuration\n');
log.calledWith('Appium Configuration\n').should.be.true;
});
it('should skip empty objects', function () {
@@ -75,7 +82,7 @@ describe('Config', function () {
{spam: 'food'},
{}
);
dir.should.have.been.calledWith({foo: 'bar', sheep: 0, ducks: false});
dir.calledWith({foo: 'bar', sheep: 0, ducks: false}).should.be.true;
});
});
@@ -88,7 +95,7 @@ describe('Config', function () {
{spam: 'food'},
{}
);
log.should.have.been.calledWith('\n(no configuration file loaded)');
log.calledWith('\n(no configuration file loaded)').should.be.true;
});
});
@@ -96,7 +103,7 @@ describe('Config', function () {
it('should not dump CLI args', function () {
// @ts-expect-error
showConfig({}, {}, {}, {});
log.should.have.been.calledWith('\n(no CLI parameters provided)');
log.calledWith('\n(no CLI parameters provided)').should.be.true;
});
});
});
@@ -6,8 +6,6 @@ import {resetSchema} from '../../../lib/schema';
import {resolveFixture, rewiremock} from '../../helpers';
import {initMocks} from './mocks';
const {expect} = chai;
describe('DriverConfig', function () {
/** @type {string} */
let yamlFixture;
@@ -31,7 +29,15 @@ describe('DriverConfig', function () {
*/
let DriverConfig;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
yamlFixture = await fs.readFile(resolveFixture('manifest', 'v3.yaml'), 'utf8');
});
@@ -338,7 +344,7 @@ describe('DriverConfig', function () {
driverConfig.readExtensionSchema(extName, extData);
// we don't have access to the schema registration cache directly, so this is as close as we can get.
expect(MockResolveFrom).to.have.been.calledOnce;
MockResolveFrom.calledOnce.should.be.true;
});
});
});
@@ -5,8 +5,6 @@ import sinon from 'sinon';
import {FAKE_DRIVER_DIR} from '../../helpers';
import {Manifest} from '../../../lib/extension/manifest';
const {expect} = chai;
/**
* Relative path from actual `package.json` of `FakeDriver` for the `fake-stdin` script
*/
@@ -20,6 +18,16 @@ describe('ExtensionCommand', function () {
/** @type {sinon.SinonSandbox} */
let sandbox;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
});
beforeEach(function () {
sandbox = sinon.createSandbox();
const driverConfig = DriverConfig.create(sandbox.createStubInstance(Manifest));
@@ -4,8 +4,6 @@ import {version as APPIUM_VER} from '../../../package.json';
import {FAKE_DRIVER_DIR, PROJECT_ROOT, rewiremock} from '../../helpers';
import {initMocks} from './mocks';
const {expect} = chai;
describe('ExtensionConfig', function () {
/** @type {import('sinon').SinonSandbox} */
let sandbox;
@@ -19,6 +17,16 @@ describe('ExtensionConfig', function () {
/** @type {import('./mocks').MockAppiumSupport} */
let MockAppiumSupport;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
});
beforeEach(function () {
let overrides;
({MockAppiumSupport, overrides, sandbox} = initMocks());
@@ -270,9 +278,9 @@ describe('ExtensionConfig', function () {
it('should display a warning count of 1', async function () {
await config._validate({foo: {}});
expect(MockAppiumSupport.logger.__logger.warn).to.be.calledWith(
MockAppiumSupport.logger.__logger.warn.calledWith(
'Appium encountered 1 warning while validating drivers found in manifest /some/path/extensions.yaml'
);
).should.be.true;
});
});
@@ -284,9 +292,9 @@ describe('ExtensionConfig', function () {
it('should display an error count of 1', async function () {
await config._validate({foo: {}});
expect(MockAppiumSupport.logger.__logger.error).to.be.calledWith(
MockAppiumSupport.logger.__logger.error.calledWith(
'Appium encountered 1 error while validating drivers found in manifest /some/path/extensions.yaml'
);
).should.be.true;
});
});
});
@@ -2,9 +2,17 @@ import {Manifest} from '../../../lib/extension/manifest';
import {migrate} from '../../../lib/extension/manifest-migrations';
import {DRIVER_TYPE} from '../../../lib/constants';
const {expect} = chai;
describe('manifest-migrations', function () {
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
});
describe('when no installPath property present in manifest', function () {
it('should trigger refresh', async function () {
const manifest = Manifest.getInstance(process.cwd());
@@ -7,8 +7,6 @@ import {initMocks} from './mocks';
import {version as APPIUM_VER} from '../../../package.json';
import EventEmitter from 'events';
const {expect} = chai;
describe('Manifest', function () {
/**
* @type {sinon.SinonSandbox}
@@ -27,7 +25,15 @@ describe('Manifest', function () {
/** @type {import('./mocks').MockGlob} */
let MockGlob;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
yamlFixture = await fs.readFile(resolveFixture('manifest', 'v3.yaml'), 'utf8');
});
@@ -143,7 +149,7 @@ describe('Manifest', function () {
});
it('should create a new file', function () {
expect(MockAppiumSupport.fs.writeFile).to.be.calledOnce;
MockAppiumSupport.fs.writeFile.calledOnce.should.be.true;
});
});
@@ -179,10 +185,10 @@ describe('Manifest', function () {
await B.all([manifest.read(), manifest.read()]);
});
it('should not read the file twice', function () {
expect(MockAppiumSupport.fs.readFile).to.have.been.calledOnceWith(
MockAppiumSupport.fs.readFile.calledOnceWith(
'/some/path/extensions.yaml',
'utf8'
);
).should.be.true;
});
});
@@ -193,15 +199,16 @@ describe('Manifest', function () {
});
it('should attempt to read the file at `filepath`', function () {
expect(MockAppiumSupport.fs.readFile).to.have.been.calledOnceWith(
MockAppiumSupport.fs.readFile.calledOnceWith(
'/some/path/extensions.yaml',
'utf8'
);
).should.be.true;
});
describe('when the data has not changed', function () {
it('should not write the data', function () {
expect(manifest.write).not.to.be.called;
// @ts-ignore
manifest.write.called.should.be.false;
});
});
@@ -218,12 +225,13 @@ describe('Manifest', function () {
it('should synchronize manifest with installed extensions', async function () {
await manifest.read();
expect(manifest.syncWithInstalledExtensions).to.be.calledOnce;
// @ts-ignore
manifest.syncWithInstalledExtensions.calledOnce.should.be.true;
});
it('should check if the `package.json` has changed', async function () {
await manifest.read();
expect(MockPackageChanged.isPackageChanged).to.be.calledOnce;
MockPackageChanged.isPackageChanged.calledOnce.should.be.true;
});
});
});
@@ -258,7 +266,7 @@ describe('Manifest', function () {
describe('when called again before the first call resolves', function () {
it('should not write the file twice', async function () {
await B.all([manifest.write(), manifest.write()]);
expect(MockAppiumSupport.fs.writeFile).to.have.been.calledOnce;
MockAppiumSupport.fs.writeFile.calledOnce.should.be.true;
});
});
@@ -4,8 +4,6 @@ import {PKG_HASHFILE_RELATIVE_PATH} from '../../../lib/constants';
import {rewiremock} from '../../helpers';
import {initMocks} from './mocks';
const {expect} = chai;
describe('package-changed', function () {
/** @type {typeof import('appium/lib/extension/package-changed').packageDidChange} */
let packageDidChange;
@@ -19,6 +17,16 @@ describe('package-changed', function () {
/** @type {import('./mocks').MockAppiumSupport} */
let MockAppiumSupport;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
});
beforeEach(function () {
({MockPackageChanged, MockAppiumSupport, sandbox} = initMocks());
({packageDidChange} = rewiremock.proxy(
@@ -46,17 +54,17 @@ describe('package-changed', function () {
it('it should attempt to create the parent dir for the hash file', async function () {
await packageDidChange('/some/path');
expect(MockAppiumSupport.fs.mkdirp).to.have.been.calledWith(
MockAppiumSupport.fs.mkdirp.calledWith(
path.dirname(path.join('/some/path', PKG_HASHFILE_RELATIVE_PATH))
);
).should.be.true;
});
it('should call `package-changed` with a cwd and relative path to hash file', async function () {
await packageDidChange('/some/path');
expect(MockPackageChanged.isPackageChanged).to.have.been.calledWith({
MockPackageChanged.isPackageChanged.calledWith({
cwd: '/some/path',
hashFilename: PKG_HASHFILE_RELATIVE_PATH,
});
}).should.be.true;
});
describe('when it cannot create the parent dir', function () {
@@ -85,14 +93,14 @@ describe('package-changed', function () {
it('should not write the hash file', async function () {
await packageDidChange('/some/where');
expect(MockPackageChanged.__writeHash).not.to.have.been.called;
MockPackageChanged.__writeHash.called.should.be.false;
});
});
describe('when the package has changed per `package-changed`', function () {
it('should write the hash file', async function () {
await packageDidChange('/some/where');
expect(MockPackageChanged.__writeHash).to.have.been.calledOnce;
MockPackageChanged.__writeHash.calledOnce.should.be.true;
});
it('should resolve `true`', async function () {
@@ -6,8 +6,6 @@ import {resetSchema} from '../../../lib/schema';
import {resolveFixture, rewiremock} from '../../helpers';
import {initMocks} from './mocks';
const {expect} = chai;
describe('PluginConfig', function () {
/** @type {string} */
let yamlFixture;
@@ -31,7 +29,15 @@ describe('PluginConfig', function () {
*/
let PluginConfig;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
yamlFixture = await fs.readFile(resolveFixture('manifest', 'v3.yaml'), 'utf8');
});
@@ -337,7 +343,7 @@ describe('PluginConfig', function () {
describe('when the extension schema has not yet been registered', function () {
it('should resolve and load the extension schema file', function () {
pluginConfig.readExtensionSchema(extName, extData);
expect(MockResolveFrom).to.have.been.calledOnce;
MockResolveFrom.calledOnce.should.be.true;
});
});
});
@@ -6,6 +6,13 @@ import {rewiremock} from '../helpers';
describe('grid-register', function () {
let sandbox;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
beforeEach(function () {
sandbox = createSandbox();
});
@@ -38,18 +45,18 @@ describe('grid-register', function () {
describe('when provided a path to a config file', function () {
it('should read the config file', async function () {
await registerNode('/path/to/config-file.json');
mocks['@appium/support'].fs.readFile.should.have.been.calledOnceWith(
mocks['@appium/support'].fs.readFile.calledOnceWith(
'/path/to/config-file.json',
'utf-8'
);
).should.be.true;
});
it('should parse the config file as JSON', async function () {
sandbox.spy(JSON, 'parse');
const parseSpy = sandbox.spy(JSON, 'parse');
await registerNode('/path/to/config-file.json');
JSON.parse.should.have.been.calledOnceWith(
parseSpy.calledOnceWith(
await mocks['@appium/support'].fs.readFile.firstCall.returnValue
);
).should.be.true;
});
describe('when the config file is invalid', function () {
@@ -65,13 +72,13 @@ describe('grid-register', function () {
describe('when provided a config object', function () {
it('should not attempt to read the object as a config file', async function () {
await registerNode({my: 'config'});
mocks['@appium/support'].fs.readFile.should.not.have.been.called;
mocks['@appium/support'].fs.readFile.called.should.be.false;
});
it('should not attempt to parse any JSON', async function () {
sandbox.spy(JSON, 'parse');
const parseSpy = sandbox.spy(JSON, 'parse');
await registerNode({my: 'config'});
JSON.parse.should.not.have.been.called;
parseSpy.called.should.be.false;
});
});
});
+6 -1
View File
@@ -11,7 +11,12 @@ describe('logging', function () {
let sandbox;
let stderrSpy;
let stdoutSpy;
beforeEach(function () {
beforeEach(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
sandbox = createSandbox();
stderrSpy = sandbox.spy(process.stderr, 'write');
stdoutSpy = sandbox.spy(process.stdout, 'write');
+8
View File
@@ -14,6 +14,14 @@ const LOG_FILTERS_FIXTURE = resolveFixture('log-filters.json');
describe('parser', function () {
let p;
let should;
beforeEach(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
should = chai.should();
});
describe('Main Parser', function () {
beforeEach(function () {
@@ -3,9 +3,15 @@
import {DRIVER_TYPE} from '../../../lib/constants';
import {ArgSpec} from '../../../lib/schema/arg-spec';
const {expect} = chai;
describe('ArgSpec', function () {
let expect;
before(async function () {
const chai = await import('chai');
chai.should();
expect = chai.expect;
});
describe('class method', function () {
describe('create()', function () {
it('should return a new ArgSpec', function () {
@@ -69,9 +75,11 @@ describe('ArgSpec', function () {
});
describe('when provided the schema ID of an extension schema', function () {
expect(ArgSpec.extensionInfoFromRootSchemaId('driver-stuff.json')).to.eql({
extType: DRIVER_TYPE,
normalizedExtName: 'stuff',
it('should return an proper object', function () {
expect(ArgSpec.extensionInfoFromRootSchemaId('driver-stuff.json')).to.eql({
extType: DRIVER_TYPE,
normalizedExtName: 'stuff',
});
});
});
});
@@ -5,9 +5,17 @@ import {PLUGIN_TYPE} from '../../../lib/constants';
import {finalizeSchema, registerSchema, resetSchema} from '../../../lib/schema';
import {toParserArgs} from '../../../lib/schema/cli-args';
const {expect} = chai;
describe('cli-args', function () {
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
});
describe('toParserArgs()', function () {
/**
*
@@ -10,12 +10,12 @@ import DRIVER_SCHEMA_FIXTURE from '../../fixtures/driver-schema';
import flattenedSchemaFixture from '../../fixtures/flattened-schema';
import {rewiremock} from '../../helpers';
const {expect} = chai;
describe('schema', function () {
/** @type {sinon.SinonSandbox} */
let sandbox;
let expect;
/**
* @type {import('@appium/types').Class<import('appium/lib/schema/schema').SchemaFinalizationError>}
*/
@@ -78,6 +78,14 @@ describe('schema', function () {
*/
let RoachHotelMap;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
});
beforeEach(function () {
sandbox = createSandbox();
+9
View File
@@ -15,6 +15,15 @@ import logger from '../../lib/logger';
import {fs} from '@appium/support';
describe('utils', function () {
let should;
beforeEach(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
should = chai.should();
});
describe('parseCapsForInnerDriver()', function () {
it('should return an error if only JSONWP provided', function () {
let {error, protocol} = parseCapsForInnerDriver(BASE_CAPS);
+51
View File
@@ -3,6 +3,57 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [9.11.2](https://github.com/appium/appium/compare/@appium/base-driver@9.11.1...@appium/base-driver@9.11.2) (2024-07-10)
### Bug Fixes
* **types:** update dependency type-fest to v4.21.0 ([#20335](https://github.com/appium/appium/issues/20335)) ([8894b9a](https://github.com/appium/appium/commit/8894b9adf709646108cc8d6426bbb690550609f2))
## [9.11.1](https://github.com/appium/appium/compare/@appium/base-driver@9.11.0...@appium/base-driver@9.11.1) (2024-06-28)
### Bug Fixes
* **driver-test-support:** update dependency @types/lodash to v4.17.6 ([82e40c1](https://github.com/appium/appium/commit/82e40c1400e23f341c45d788982ccc5905827d7c))
* **images-plugin:** update dependency lru-cache to v10.3.0 ([#20306](https://github.com/appium/appium/issues/20306)) ([e43c7a4](https://github.com/appium/appium/commit/e43c7a4dce1f50fbd4d028cbeac5677422210b20))
## [9.11.0](https://github.com/appium/appium/compare/@appium/base-driver@9.10.3...@appium/base-driver@9.11.0) (2024-06-27)
### Features
* **appium:** Improve context logging ([#20250](https://github.com/appium/appium/issues/20250)) ([f675abc](https://github.com/appium/appium/commit/f675abc27b3e6beac2431cc71afb5fc2c2f70534))
### Bug Fixes
* **base-driver:** Check if app path is relative earlier ([#20276](https://github.com/appium/appium/issues/20276)) ([2882e71](https://github.com/appium/appium/commit/2882e7163159b7918d54cc4521105a1fdf55da9a))
* **base-driver:** update dependency path-to-regexp to v7 ([#20279](https://github.com/appium/appium/issues/20279)) ([a746eef](https://github.com/appium/appium/commit/a746eefbbb627c7f7dd9d1ce13226a88d9527129))
* **types:** update dependency type-fest to v4.20.1 ([#20255](https://github.com/appium/appium/issues/20255)) ([1984553](https://github.com/appium/appium/commit/19845531f558e2b16dfae807c768e1b9f2cab25d))
## [9.10.3](https://github.com/appium/appium/compare/@appium/base-driver@9.10.2...@appium/base-driver@9.10.3) (2024-06-11)
**Note:** Version bump only for package @appium/base-driver
## [9.10.2](https://github.com/appium/appium/compare/@appium/base-driver@9.10.1...@appium/base-driver@9.10.2) (2024-06-11)
**Note:** Version bump only for package @appium/base-driver
## [9.10.1](https://github.com/appium/appium/compare/@appium/base-driver@9.10.0...@appium/base-driver@9.10.1) (2024-06-11)
**Note:** Version bump only for package @appium/base-driver
@@ -20,6 +20,7 @@ import {
import B from 'bluebird';
import _ from 'lodash';
import {fixCaps, isW3cCaps} from '../helpers/capabilities';
import {calcSignature} from '../helpers/session';
import {DELETE_SESSION_COMMAND, determineProtocol, errors} from '../protocol';
import {processCapabilities, validateCaps} from './capabilities';
import {DriverCore} from './core';
@@ -309,6 +310,11 @@ export class BaseDriver<
this._log.prefix = helpers.generateDriverLogPrefix(this);
this.log.updateAsyncContext({
sessionId: this.sessionId,
sessionSignature: calcSignature(this.sessionId),
});
this.log.info(`Session created with session id: ${this.sessionId}`);
return [this.sessionId, caps] as CreateResult;
@@ -105,6 +105,14 @@ export async function configureApp(
};
const {protocol, pathname} = parseAppLink(app);
const isUrl = isSupportedUrl(app);
if (!isUrl && !path.isAbsolute(newApp)) {
newApp = path.resolve(process.cwd(), newApp);
logger.warn(
`The current application path '${app}' is not absolute ` +
`and has been rewritten to '${newApp}'. Consider using absolute paths rather than relative`
);
app = newApp;
}
const appCacheKey = toCacheKey(app);
const cachedAppInfo = APPLICATIONS_CACHE.get(appCacheKey);
@@ -276,13 +284,6 @@ export async function configureApp(
}
}
logger.info(`Unzipped local app to '${newApp}'`);
} else if (!path.isAbsolute(newApp)) {
newApp = path.resolve(process.cwd(), newApp);
logger.warn(
`The current application path '${app}' is not absolute ` +
`and has been rewritten to '${newApp}'. Consider using absolute paths rather than relative`
);
app = newApp;
}
const storeAppInCache = async (appPathToCache) => {
@@ -144,6 +144,9 @@ async function handleIdempotency(req, res, next) {
}
const key = _.isArray(keyOrArr) ? keyOrArr[0] : keyOrArr;
log.updateAsyncContext({idempotencyKey: key});
if (!MONITORED_METHODS.includes(req.method)) {
// GET, DELETE, etc. requests are idempotent by default
// there is no need to cache them
@@ -3,6 +3,8 @@ import log from './logger';
import {errors} from '../protocol';
export {handleIdempotency} from './idempotency';
import {pathToRegexp} from 'path-to-regexp';
import {util} from '@appium/support';
import {calcSignature} from '../helpers/session';
/**
*
@@ -76,15 +78,13 @@ export function fixPythonContentType(basePath) {
* @returns {any}
*/
export function handleLogContext(req, res, next) {
const contextStorage = global._global_npmlog?.asyncStorage;
if (!contextStorage) {
return next();
}
const requestId = util.uuidV4();
const sessionId = SESSION_ID_PATTERN.exec(req.url)?.[1];
const sessionInfo = sessionId ? {sessionId, sessionSignature: calcSignature(sessionId)} : {};
log.updateAsyncContext({requestId, ...sessionInfo}, true);
const sessionIdMatch = SESSION_ID_PATTERN.exec(req.url);
contextStorage.enterWith(
sessionIdMatch ? {sessionSignature: sessionIdMatch[1].substring(0, 8)} : {}
);
return next();
}
+26 -44
View File
@@ -28,10 +28,10 @@ import {
} from './websocket';
import B from 'bluebird';
import {DEFAULT_BASE_PATH} from '../constants';
import {EventEmitter} from 'events';
import {fs} from '@appium/support';
import {fs, timing} from '@appium/support';
const KEEP_ALIVE_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
const SERVER_CLOSE_TIMEOUT_MS = 5000;
/**
*
@@ -192,10 +192,6 @@ function configureServer({
* @returns {AppiumServer}
*/
function configureHttp({httpServer, reject, keepAliveTimeout}) {
const serverState = {
notifier: new EventEmitter(),
closed: false,
};
/**
* @type {AppiumServer}
*/
@@ -208,23 +204,34 @@ function configureHttp({httpServer, reject, keepAliveTimeout}) {
// http.Server.close() only stops new connections, but we need to wait until
// all connections are closed and the `close` event is emitted
const close = appiumServer.close.bind(appiumServer);
const originalClose = appiumServer.close.bind(appiumServer);
appiumServer.close = async () =>
await new B((resolve, reject) => {
// https://github.com/nodejs/node-v0.x-archive/issues/9066#issuecomment-124210576
serverState.closed = true;
serverState.notifier.emit('shutdown');
log.info('Waiting until the server is closed');
httpServer.on('close', () => {
log.info('Received server close event');
resolve();
await new B((_resolve, _reject) => {
log.info('Closing Appium HTTP server');
const timer = new timing.Timer().start();
const onTimeout = setTimeout(() => {
log.info(
`Not all active connections have been closed within ` +
`${timer.getDuration().asMilliSeconds.toFixed(0)}ms. Exiting anyway.`
);
process.exit(process.exitCode ?? 0);
}, SERVER_CLOSE_TIMEOUT_MS);
httpServer.once('close', () => {
log.info(
`Appium HTTP server has been succesfully closed after ` +
`${timer.getDuration().asMilliSeconds.toFixed(0)}ms`
);
clearTimeout(onTimeout);
_resolve();
});
close((err) => {
if (err) reject(err); // eslint-disable-line curly
originalClose((/** @type {Error|undefined} */ err) => {
if (err) {
_reject(err);
}
});
});
appiumServer.on(
appiumServer.once(
'error',
/** @param {NodeJS.ErrnoException} err */ (err) => {
if (err.code === 'EADDRNOTAVAIL') {
@@ -242,31 +249,7 @@ function configureHttp({httpServer, reject, keepAliveTimeout}) {
}
);
appiumServer.on(
'connection',
/** @param {AppiumServerSocket} socket */ (socket) => {
socket.setTimeout(keepAliveTimeout);
socket.on('error', reject);
function destroy() {
socket.destroy();
}
socket._openReqCount = 0;
socket.once('close', () => serverState.notifier.removeListener('shutdown', destroy));
serverState.notifier.once('shutdown', destroy);
}
);
appiumServer.on('request', function (req, res) {
const socket = /** @type {AppiumServerSocket} */ (req.connection || req.socket);
socket._openReqCount++;
res.on('finish', function () {
socket._openReqCount--;
if (serverState.closed && socket._openReqCount === 0) {
socket.destroy();
}
});
});
appiumServer.on('connection', (socket) => socket.setTimeout(keepAliveTimeout));
return appiumServer;
}
@@ -324,7 +307,6 @@ export {server, configureServer, normalizeBasePath};
/**
* @typedef {import('@appium/types').AppiumServer} AppiumServer
* @typedef {import('@appium/types').AppiumServerSocket} AppiumServerSocket
*/
/**
@@ -0,0 +1,8 @@
/**
* Extract the first 8 characters of session ID to prefix the log.
*
* @param sessionId session identifier
*/
export function calcSignature(sessionId: string): string {
return sessionId.substring(0, 8);
}
+32 -73
View File
@@ -3,6 +3,7 @@
import _ from 'lodash';
import {util} from '@appium/support';
import {PROTOCOLS, DEFAULT_BASE_PATH} from '../constants';
import {pathToRegexp} from 'path-to-regexp';
const SET_ALERT_TEXT_PAYLOAD_PARAMS = {
validate: (jsonObj) =>
@@ -20,7 +21,7 @@ const SET_ALERT_TEXT_PAYLOAD_PARAMS = {
* `optional`
* @satisfies {import('@appium/types').MethodMap<import('../basedriver/driver').BaseDriver>}
*/
const METHOD_MAP = /** @type {const} */ ({
export const METHOD_MAP = /** @type {const} */ ({
'/status': {
GET: {command: 'getStatus'},
},
@@ -918,90 +919,48 @@ const METHOD_MAP = /** @type {const} */ ({
});
// driver command names
let ALL_COMMANDS = [];
for (let v of _.values(METHOD_MAP)) {
for (let m of _.values(v)) {
if ('command' in m && m.command) {
ALL_COMMANDS.push(m.command);
}
}
}
const RE_ESCAPE = /[-[\]{}()+?.,\\^$|#\s]/g;
const RE_PARAM = /([:*])(\w+)/g;
class Route {
constructor(route) {
this.paramNames = [];
let reStr = route.replace(RE_ESCAPE, '\\$&');
reStr = reStr.replace(RE_PARAM, (_, mode, name) => {
this.paramNames.push(name);
return mode === ':' ? '([^/]*)' : '(.*)';
});
this.routeRegexp = new RegExp(`^${reStr}$`);
}
parse(url) {
//if (url.indexOf('timeouts') !== -1 && this.routeRegexp.toString().indexOf('timeouts') !== -1) {
//debugger;
//}
let matches = url.match(this.routeRegexp);
if (!matches) return; // eslint-disable-line curly
let i = 0;
let params = {};
while (i < this.paramNames.length) {
const paramName = this.paramNames[i++];
params[paramName] = matches[i];
}
return params;
}
}
export const ALL_COMMANDS = _.flatMap(_.values(METHOD_MAP).map(_.values))
.filter((m) => Boolean(m.command))
.map((m) => m.command);
/**
*
* @param {string} endpoint
* @param {import('@appium/types').HTTPMethod} method
* @param {string} [basePath]
* @param {string} [basePath=DEFAULT_BASE_PATH]
* @returns {string|undefined}
*/
function routeToCommandName(endpoint, method, basePath = DEFAULT_BASE_PATH) {
let dstRoute = null;
// remove any query string
// TODO: would this be better handled as a `URL` object?
if (endpoint.includes('?')) {
endpoint = endpoint.slice(0, endpoint.indexOf('?'));
export function routeToCommandName(endpoint, method, basePath = DEFAULT_BASE_PATH) {
let normalizedEndpoint = basePath
? endpoint.replace(new RegExp(`^${_.escapeRegExp(basePath)}`), '')
: endpoint;
normalizedEndpoint = `${_.startsWith(normalizedEndpoint, '/') ? '' : '/'}${normalizedEndpoint}`;
/** @type {string} */
let normalizedPathname;
try {
// we could use any prefix there as we anyway need to only extract the pathname
normalizedPathname = new URL(`https://appium.io${normalizedEndpoint}`).pathname;
} catch (err) {
throw new Error(`'${endpoint}' cannot be translated to a command name: ${err.message}`);
}
const actualEndpoint =
endpoint === '/' ? '' : _.startsWith(endpoint, '/') ? endpoint : `/${endpoint}`;
for (let currentRoute of _.keys(METHOD_MAP)) {
const route = new Route(`${basePath}${currentRoute}`);
// we don't care about the actual session id for matching
if (
route.parse(`${basePath}/session/ignored-session-id${actualEndpoint}`) ||
route.parse(`${basePath}${actualEndpoint}`) ||
route.parse(actualEndpoint)
) {
dstRoute = currentRoute;
break;
}
/** @type {string[]} */
const possiblePathnames = [];
if (!normalizedPathname.startsWith('/session/')) {
possiblePathnames.push(`/session/any-session-id${normalizedPathname}`);
}
if (!dstRoute) return; // eslint-disable-line curly
const methods = METHOD_MAP[dstRoute];
method = /** @type {Uppercase<typeof method>} */ (_.toUpper(method));
if (method in methods) {
const dstMethod = _.get(methods, method);
if (dstMethod.command) {
return dstMethod.command;
possiblePathnames.push(normalizedPathname);
const normalizedMethod = _.toUpper(method);
for (const [routePath, routeSpec] of _.toPairs(METHOD_MAP)) {
const routeRegexp = pathToRegexp(routePath);
if (possiblePathnames.some((pp) => routeRegexp.test(pp))) {
const commandName = routeSpec?.[normalizedMethod]?.command;
if (commandName) {
return commandName;
}
}
}
}
// driver commands that do not require a session to already exist
const NO_SESSION_ID_COMMANDS = ['createSession', 'getStatus', 'getSessions'];
export {METHOD_MAP, ALL_COMMANDS, NO_SESSION_ID_COMMANDS, routeToCommandName};
export const NO_SESSION_ID_COMMANDS = ['createSession', 'getStatus', 'getSessions'];
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/base-driver",
"version": "9.10.1",
"version": "9.11.2",
"description": "Base driver class for Appium drivers",
"keywords": [
"automation",
@@ -44,13 +44,13 @@
"test:types": "tsd"
},
"dependencies": {
"@appium/support": "^5.0.1",
"@appium/types": "^0.20.1",
"@appium/support": "^5.1.2",
"@appium/types": "^0.21.1",
"@colors/colors": "1.6.0",
"@types/async-lock": "1.4.2",
"@types/bluebird": "3.5.42",
"@types/express": "4.17.21",
"@types/lodash": "4.17.5",
"@types/lodash": "4.17.6",
"@types/method-override": "0.0.35",
"@types/serve-favicon": "2.5.7",
"async-lock": "1.4.1",
@@ -61,13 +61,13 @@
"express": "4.19.2",
"http-status-codes": "2.3.0",
"lodash": "4.17.21",
"lru-cache": "10.2.2",
"lru-cache": "10.3.0",
"method-override": "3.0.0",
"morgan": "1.10.0",
"path-to-regexp": "6.2.2",
"path-to-regexp": "7.0.0",
"serve-favicon": "2.5.0",
"source-map-support": "0.5.21",
"type-fest": "4.20.0",
"type-fest": "4.21.0",
"validate.js": "0.13.1"
},
"optionalDependencies": {
@@ -15,6 +15,13 @@ function getFixture(file) {
}
describe('app download and configuration', function () {
before(async function () {
const chai = await import('chai');
const chaisAsPromised = await import('chai-as-promised');
chai.use(chaisAsPromised.default);
chai.should();
});
describe('configureApp', function () {
it('should get the path for a local .app', async function () {
let newAppPath = await configureApp(getFixture('FakeIOSApp.app'), '.app');
@@ -13,6 +13,11 @@ describe('Websockets (e2e)', function () {
const WS_DATA = 'Hello';
before(async function () {
const chai = await import('chai');
const chaisAsPromised = await import('chai-as-promised');
chai.use(chaisAsPromised.default);
chai.should();
driver = new FakeDriver();
driver.sessionId = SESSION_ID;
port = await getTestPort();
@@ -21,6 +21,11 @@ describe('server', function () {
let port;
let sandbox;
before(async function () {
const chai = await import('chai');
const chaisAsPromised = await import('chai-as-promised');
chai.use(chaisAsPromised.default);
chai.should();
port = await getTestPort(true);
function configureRoutes(app) {
@@ -119,6 +124,11 @@ describe('tls server', function () {
});
before(async function () {
const chai = await import('chai');
const chaisAsPromised = await import('chai-as-promised');
chai.use(chaisAsPromised.default);
chai.should();
try {
await generateCertificate(certPath, keyPath);
} catch (e) {
@@ -167,6 +177,11 @@ describe('server plugins', function () {
let port;
before(async function () {
const chai = await import('chai');
const chaisAsPromised = await import('chai-as-promised');
chai.use(chaisAsPromised.default);
chai.should();
port = await getTestPort(true);
});
@@ -4,7 +4,14 @@ import {FakeDriver} from '../protocol/fake-driver';
describe('proxy', function () {
const jwproxy = new JWProxy();
let baseServer;
let should;
before(async function () {
const chai = await import('chai');
const chaisAsPromised = await import('chai-as-promised');
chai.use(chaisAsPromised.default);
should = chai.should();
baseServer = await server({
routeConfiguringFunction: routeConfiguringFunction(new FakeDriver()),
port: 4444,
@@ -12,6 +12,7 @@ let baseUrl;
describe('Protocol', function () {
let sandbox;
let should;
beforeEach(function () {
sandbox = createSandbox();
@@ -22,6 +23,11 @@ describe('Protocol', function () {
});
before(async function () {
const chai = await import('chai');
const chaisAsPromised = await import('chai-as-promised');
chai.use(chaisAsPromised.default);
should = chai.should();
port = await getTestPort();
baseUrl = `http://${TEST_HOST}:${port}`;
});
@@ -14,6 +14,15 @@ import {BASE_DESIRED_CAP_CONSTRAINTS} from '@appium/types';
import {isW3cCaps} from '../../../lib/helpers/capabilities';
describe('caps', function () {
let should;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
should = chai.should();
});
// Tests based on: https://www.w3.org/TR/webdriver/#dfn-validate-caps
describe('#validateCaps', function () {
it('returns invalid argument error if "capability" is not a JSON object (1)', function () {
@@ -11,12 +11,24 @@ describe('Desired Capabilities', function () {
/** @type {BaseDriver} */
let d;
let sandbox;
/** @type {import('sinon').SinonSpy} */
let logWarnSpy;
/** @type {import('sinon').SinonStub} */
let deprecatedStub;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
beforeEach(function () {
d = new BaseDriver();
sandbox = createSandbox();
sandbox.spy(d.log, 'warn');
sandbox.stub(validator.validators, 'deprecated');
logWarnSpy = sandbox.spy(d.log, 'warn');
deprecatedStub = sandbox.stub(validator.validators, 'deprecated');
});
afterEach(function () {
@@ -118,7 +130,7 @@ describe('Desired Capabilities', function () {
firstMatch: [{}],
});
d.log.warn.should.have.been.called;
logWarnSpy.called.should.be.true;
});
it('should be sensitive to the case of caps', async function () {
@@ -143,7 +155,7 @@ describe('Desired Capabilities', function () {
},
firstMatch: [{}],
});
d.log.warn.should.have.been.called;
logWarnSpy.called.should.be.true;
let sessions = await d.getSessions();
sessions[0].capabilities.noReset.should.eql(false);
@@ -158,7 +170,7 @@ describe('Desired Capabilities', function () {
},
firstMatch: [{}],
});
d.log.warn.should.have.been.called;
logWarnSpy.called.should.be.true;
let sessions = await d.getSessions();
sessions[0].capabilities.noReset.should.eql(true);
@@ -172,7 +184,7 @@ describe('Desired Capabilities', function () {
},
firstMatch: [{}],
});
d.log.warn.should.not.have.been.called;
logWarnSpy.called.should.be.false;
let sessions = await d.getSessions();
sessions[0].capabilities.language.should.eql('true');
@@ -189,7 +201,7 @@ describe('Desired Capabilities', function () {
},
firstMatch: [{}],
});
d.log.warn.should.have.been.called;
logWarnSpy.called.should.be.true;
let sessions = await d.getSessions();
sessions[0].capabilities.newCommandTimeout.should.eql(1);
@@ -204,7 +216,7 @@ describe('Desired Capabilities', function () {
},
firstMatch: [{}],
});
d.log.warn.should.have.been.called;
logWarnSpy.called.should.be.true;
let sessions = await d.getSessions();
sessions[0].capabilities.newCommandTimeout.should.eql(1.1);
@@ -218,7 +230,7 @@ describe('Desired Capabilities', function () {
},
firstMatch: [{}],
});
d.log.warn.should.not.have.been.called;
logWarnSpy.called.should.be.false;
let sessions = await d.getSessions();
sessions[0].capabilities.language.should.eql('1');
@@ -254,7 +266,7 @@ describe('Desired Capabilities', function () {
firstMatch: [{}],
});
validator.validators.deprecated.should.have.been.calledWith(5, true, 'lynx-version');
(deprecatedStub.calledWith(5, true, 'lynx-version')).should.be.true;
});
it('should not warn if deprecated=false', async function () {
@@ -274,7 +286,7 @@ describe('Desired Capabilities', function () {
firstMatch: [{}],
});
d.log.warn.should.not.have.been.called;
logWarnSpy.called.should.be.false;
});
it('should not validate against null/undefined caps', async function () {
@@ -2,6 +2,13 @@ import _ from 'lodash';
import {BaseDriver} from '../../../../lib';
describe('logging custom events', function () {
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
it('should allow logging of events', async function () {
const d = new BaseDriver();
d._eventHistory.should.eql({commands: []});
@@ -19,6 +26,13 @@ describe('logging custom events', function () {
});
describe('#getLogEvents', function () {
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
it('should allow to get all events', async function () {
const d = new BaseDriver();
d._eventHistory.should.eql({commands: []});
@@ -3,8 +3,6 @@ import {createSandbox} from 'sinon';
import _ from 'lodash';
import BaseDriver from '../../../../lib';
const expect = chai.expect;
const FIRST_LOGS = ['first', 'logs'];
const SECOND_LOGS = ['second', 'logs'];
const SUPPORTED_LOG_TYPES = {
@@ -20,8 +18,14 @@ const SUPPORTED_LOG_TYPES = {
describe('log commands -', function () {
let sandbox;
let driver;
let expect;
before(async function () {
const chai = await import('chai');
chai.should();
expect = chai.expect;
});
beforeEach(function () {
sandbox = createSandbox();
@@ -3,10 +3,17 @@ import sinon from 'sinon';
import {DeviceSettings, MAX_SETTINGS_SIZE} from '../../../lib/basedriver/device-settings';
import {InvalidArgumentError} from '../../../lib/protocol/errors';
const {expect} = chai;
describe('DeviceSettings', function () {
let sandbox;
let expect;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
expect = chai.expect;
});
beforeEach(function () {
sandbox = sinon.createSandbox();
@@ -91,7 +98,7 @@ describe('DeviceSettings', function () {
it('should not call the `_onSettingsUpdate` listener', async function () {
const deviceSettings = new DeviceSettings({stuff: 'things'}, onSettingsUpdate);
await deviceSettings.update({stuff: 'things'});
expect(onSettingsUpdate).not.to.have.been.called;
onSettingsUpdate.called.should.be.false;
});
});
@@ -99,11 +106,11 @@ describe('DeviceSettings', function () {
it('should call the `_onSettingsUpdate` listener', async function () {
const deviceSettings = new DeviceSettings({}, onSettingsUpdate);
await deviceSettings.update({stuff: 'things'});
expect(onSettingsUpdate).to.have.been.calledOnceWithExactly(
onSettingsUpdate.calledOnceWithExactly(
'stuff',
'things',
undefined
);
).should.be.true;
});
});
});
@@ -1,14 +1,20 @@
import BaseDriver from '../../../lib';
import {driverUnitTestSuite} from '@appium/driver-test-support';
const {expect} = chai;
driverUnitTestSuite(BaseDriver, {
platformName: 'iOS',
'appium:deviceName': 'Delorean',
});
describe('BaseDriver', function () {
let expect;
before(async function () {
const chai = await import('chai');
chai.should();
expect = chai.expect;
});
describe('constructor', function () {
it('should initialize "opts"', function () {
const driver = new BaseDriver();
@@ -8,6 +8,15 @@ import {
import sinon from 'sinon';
describe('helpers', function () {
let should;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
should = chai.should();
});
describe('#isPackageOrBundle', function () {
it('should accept packages and bundles', function () {
isPackageOrBundle('io.appium.testapp').should.be.true;
@@ -4,6 +4,13 @@ import BaseDriver from '../../../lib';
import {createSandbox} from 'sinon';
describe('timeout', function () {
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
let driver = new BaseDriver();
let implicitWaitSpy;
let sandbox;
@@ -0,0 +1,24 @@
import {pathToRegexp} from 'path-to-regexp';
describe('middleware', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
describe('pathToRegexp', function () {
it('should match static path pattern', function () {
const pathname = '/ws/session/1234/appium/device/syslog';
const url = 'ws://127.0.0.1:8000/ws/session/1234/appium/device/syslog';
const currentPathname = new URL(url).pathname;
pathToRegexp(pathname).test(currentPathname).should.be.true;
});
it('should match dynamic path pattern', function () {
const pathname = '/ws/session/:sessionId/appium/device/syslog';
const url = 'ws://127.0.0.1:8000/ws/session/1234/appium/device/syslog';
const currentPathname = new URL(url).pathname;
pathToRegexp(pathname).test(currentPathname).should.be.true;
});
});
});
@@ -23,8 +23,15 @@ function fakeDriver() {
describe('server configuration', function () {
let port;
let sandbox;
let should;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
should = chai.should();
});
function fakeApp() {
const app = {
@@ -6,6 +6,11 @@ import {createSandbox} from 'sinon';
describe('welcome', function () {
let sandbox;
before(async function () {
const chai = await import('chai');
chai.should();
});
beforeEach(function () {
sandbox = createSandbox();
});
@@ -7,6 +7,13 @@ import ProtocolConverter, {
const {MJSONWP, W3C} = PROTOCOLS;
describe('Protocol Converter', function () {
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
describe('getTimeoutRequestObjects', function () {
let converter;
before(function () {
@@ -25,6 +25,14 @@ function buildReqRes(url, method, body) {
describe('proxy', function () {
let port;
let should;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
should = chai.should();
});
function mockProxy(opts = {}) {
// sets default server/port
@@ -21,6 +21,11 @@ describe('JWProxy', function () {
}
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
port = await getTestPort();
createTestURL = createAppiumURL(TEST_HOST, port);
testStatusURL = createTestURL('', 'status');
@@ -2,6 +2,15 @@ import _ from 'lodash';
import {statusCodes, getSummaryByCode} from '../../../lib';
describe('jsonwp-status', function () {
let should;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
should = chai.should();
});
describe('codes', function () {
it('should export code numbers and summaries', function () {
for (let obj of _.values(statusCodes)) {
@@ -227,6 +227,11 @@ let errorsList = [
];
describe('errors', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
for (let error of errorsList) {
it(error.errorName + ' should have a JSONWP code or W3C code and message', function () {
if (error.errorCode) {
@@ -247,6 +252,11 @@ describe('errors', function () {
});
});
describe('errorFromMJSONWPStatusCode', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
for (let error of errorsList) {
if (error.errorName !== 'NotYetImplementedError') {
it(error.errorCode + ' should return correct error', function () {
@@ -285,6 +295,11 @@ describe('errorFromMJSONWPStatusCode', function () {
});
});
describe('errorFromW3CJsonCode', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
for (let error of errorsList) {
if (error.errorName !== 'NotYetImplementedError') {
it(error.errorName + ' should return correct error', function () {
@@ -307,6 +322,11 @@ describe('errorFromW3CJsonCode', function () {
});
});
describe('w3c Status Codes', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
it('should match the correct error codes', function () {
let non400Errors = [
['NoSuchDriverError', 404],
@@ -341,6 +361,11 @@ describe('w3c Status Codes', function () {
});
});
describe('.getResponseForW3CError', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
it('should return an error, message and stacktrace for just a generic exception', function () {
try {
throw new Error('Some random error');
@@ -388,6 +413,11 @@ describe('.getResponseForW3CError', function () {
});
});
describe('.getActualError', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
describe('MJSONWP', function () {
it('should map a status code 7 no such element error as a NoSuchElementError', function () {
const actualError = new errors.ProxyRequestError('Error message does not matter', {
@@ -7,6 +7,14 @@ import crypto from 'crypto';
describe('Protocol', function () {
// TODO test against an explicit protocol rather than a hash of a previous
// protocol
let chai;
before(async function () {
chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
describe('ensure protocol consistency', function () {
it('should not change protocol between patch versions', function () {
@@ -55,6 +63,16 @@ describe('Protocol', function () {
cmdName.should.equal('getStatus');
});
it('should properly lookup correct command name for endpoint with query params', function () {
const cmdName = routeToCommandName('/status?foo=1&bar=2', 'GET');
cmdName.should.equal('getStatus');
});
it('should properly lookup correct command name with custom base path', function () {
const cmdName = routeToCommandName('/wd/hub/status?foo=1&bar=2', 'GET', '/wd/hub');
cmdName.should.equal('getStatus');
});
it('should properly lookup correct command name for endpoint without leading slash', function () {
const cmdName = routeToCommandName('status', 'GET');
cmdName.should.equal('getStatus');
@@ -3,6 +3,11 @@
import {validators} from '../../../lib/protocol/validators';
describe('Protocol', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
describe('direct to driver', function () {
describe('setUrl', function () {
it('should fail when no url passed', function () {
+40
View File
@@ -3,6 +3,46 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.2.42](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.41...@appium/base-plugin@2.2.42) (2024-07-10)
**Note:** Version bump only for package @appium/base-plugin
## [2.2.41](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.40...@appium/base-plugin@2.2.41) (2024-06-28)
**Note:** Version bump only for package @appium/base-plugin
## [2.2.40](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.39...@appium/base-plugin@2.2.40) (2024-06-27)
**Note:** Version bump only for package @appium/base-plugin
## [2.2.39](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.38...@appium/base-plugin@2.2.39) (2024-06-11)
**Note:** Version bump only for package @appium/base-plugin
## [2.2.38](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.37...@appium/base-plugin@2.2.38) (2024-06-11)
**Note:** Version bump only for package @appium/base-plugin
## [2.2.37](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.36...@appium/base-plugin@2.2.37) (2024-06-11)
**Note:** Version bump only for package @appium/base-plugin
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/base-plugin",
"version": "2.2.37",
"version": "2.2.42",
"description": "The base plugin used to create Appium 2.0 plugins",
"keywords": [
"automation",
@@ -40,8 +40,8 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/base-driver": "^9.10.1",
"@appium/support": "^5.0.1"
"@appium/base-driver": "^9.11.2",
"@appium/support": "^5.1.2"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
@@ -1,6 +1,13 @@
import BasePlugin from '../../lib/plugin';
describe('base plugin', function () {
let should;
before(async function () {
const chai = await import('chai');
should = chai.should();
});
it('should exist', function () {
should.exist(BasePlugin);
});
+49
View File
@@ -3,6 +3,55 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.1.9](https://github.com/appium/appium/compare/@appium/doctor@2.1.8...@appium/doctor@2.1.9) (2024-07-10)
### Bug Fixes
* **doctor:** update dependency appium-adb to v12.4.6 ([5281f5a](https://github.com/appium/appium/commit/5281f5a01a63e12454093cb296286da02adc77ee))
* **doctor:** update dependency appium-adb to v12.4.8 ([177dff4](https://github.com/appium/appium/commit/177dff4f0ed84880ce9df55f94ff62b922a80ae5))
* **support:** update dependency teen_process to v2.1.10 ([86f843b](https://github.com/appium/appium/commit/86f843b9e1fc56576d7a08bf95838a58971e98b3))
* **support:** update dependency teen_process to v2.1.7 ([5226fa8](https://github.com/appium/appium/commit/5226fa897b90e9fec9be3e79a7d48fc7b4e0016d))
* **support:** update dependency teen_process to v2.2.0 ([06607da](https://github.com/appium/appium/commit/06607da92e93d015747fd6d6d5bdabe1b3ac58d2))
## [2.1.8](https://github.com/appium/appium/compare/@appium/doctor@2.1.7...@appium/doctor@2.1.8) (2024-06-28)
**Note:** Version bump only for package @appium/doctor
## [2.1.7](https://github.com/appium/appium/compare/@appium/doctor@2.1.6...@appium/doctor@2.1.7) (2024-06-27)
### Bug Fixes
* **doctor:** update dependency appium-adb to v12.4.3 ([4345a40](https://github.com/appium/appium/commit/4345a40a15d2473bb13524593ab66ff8ae3d8a7e))
* **doctor:** update dependency appium-adb to v12.4.4 ([15234bc](https://github.com/appium/appium/commit/15234bc05502157ebf847856d38e35da4d542df7))
* **support:** update dependency teen_process to v2.1.5 ([bc388db](https://github.com/appium/appium/commit/bc388db1116f411f4b241105f5feae30418c9a27))
* **support:** update dependency teen_process to v2.1.6 ([5412461](https://github.com/appium/appium/commit/541246184dc7521c825ec1902775e681ea6f0db3))
## [2.1.6](https://github.com/appium/appium/compare/@appium/doctor@2.1.5...@appium/doctor@2.1.6) (2024-06-11)
**Note:** Version bump only for package @appium/doctor
## [2.1.5](https://github.com/appium/appium/compare/@appium/doctor@2.1.4...@appium/doctor@2.1.5) (2024-06-11)
**Note:** Version bump only for package @appium/doctor
## [2.1.4](https://github.com/appium/appium/compare/@appium/doctor@2.1.3...@appium/doctor@2.1.4) (2024-06-11)
**Note:** Version bump only for package @appium/doctor
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/doctor",
"version": "2.1.4",
"version": "2.1.9",
"description": "Test environment for fitness to run Appium",
"keywords": [
"automation",
@@ -44,16 +44,16 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/support": "^5.0.1",
"@appium/support": "^5.1.2",
"@colors/colors": "1.6.0",
"@types/bluebird": "3.5.42",
"@types/teen_process": "2.0.4",
"appium-adb": "12.4.2",
"appium-adb": "12.4.8",
"bluebird": "3.7.2",
"inquirer": "9.2.12",
"lodash": "4.17.21",
"source-map-support": "0.5.21",
"teen_process": "2.1.4",
"teen_process": "2.2.0",
"yargs": "17.7.2"
},
"engines": {
@@ -18,6 +18,14 @@ describe('android', function () {
const apkAnalyzerFilename = system.isWindows() ? 'apkanalyzer.bat' : 'apkanalyzer';
const gstLaunchFilename = system.isWindows() ? 'gst-launch-1.0.exe' : 'gst-launch-1.0';
const gstInspectFilename = system.isWindows() ? 'gst-inspect-1.0.exe' : 'gst-inspect-1.0';
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
describe(
'EnvVarAndPathCheck',
withMocks({fs}, (mocks) => {
+7
View File
@@ -8,6 +8,13 @@ import {withMocks, withSandbox, stubLog} from '@appium/test-support';
import B from 'bluebird';
describe('demo', function () {
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
describe(
'DirCheck',
withMocks({fs}, (mocks) => {
+7
View File
@@ -7,6 +7,13 @@ import B from 'bluebird';
import {removeColors} from './helper';
describe('dev', function () {
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
describe(
'BinaryIsInPathCheck',
withMocks({tp, fs}, (mocks) => {
+7
View File
@@ -4,6 +4,13 @@ import log from '../../lib/logger';
import B from 'bluebird';
describe('doctor', function () {
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
it('register', function () {
let doctor = new Doctor();
doctor.checks.should.have.length(0);
@@ -1,6 +1,11 @@
import newDoctor from '../../lib/factory';
describe('factory', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
function getTest(config) {
return function runTest() {
let doctor = newDoctor(config);
@@ -12,6 +12,13 @@ import B from 'bluebird';
import {removeColors} from './helper';
describe('general', function () {
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
describe(
'NodeBinaryCheck',
withMocks({NodeDetector}, (mocks) => {
+5
View File
@@ -1,6 +1,11 @@
import {newDoctor, Doctor, DoctorCheck} from '../../lib';
describe('index', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
it('should work', function () {
newDoctor.should.exist;
Doctor.should.exist;
+7
View File
@@ -19,6 +19,13 @@ import {withMocks, withSandbox, stubLog} from '@appium/test-support';
import {removeColors} from './helper';
describe('ios', function () {
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
describe(
'XcodeCheck',
withMocks({tp, fs}, (mocks) => {
@@ -3,11 +3,18 @@ import NodeDetector from '../../lib/node-detector';
import B from 'bluebird';
import {withSandbox} from '@appium/test-support';
let expect = chai.expect;
describe(
'NodeDetector',
withSandbox({mocks: {fs, system}}, (S) => {
let expect;
before(async function () {
const chai = await import('chai');
chai.should();
expect = chai.expect;
});
it('retrieveUsingSystemCall - success - where returns multiple lines ', async function () {
S.mocks.fs.expects('which').once().returns(B.resolve('/a/b/node.exe'));
S.mocks.fs.expects('exists').once().returns(B.resolve(true));
+5
View File
@@ -6,6 +6,11 @@ import B from 'bluebird';
describe(
'prompt',
withMocks({utils}, (mocks) => {
before(async function () {
const chai = await import('chai');
chai.should();
});
it('fixit - yes', async function () {
clear();
mocks.utils
+5
View File
@@ -4,6 +4,11 @@ import path from 'path';
import {Doctor} from '../../lib/doctor';
describe('utils', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
it('fs.readFile', async function () {
(await fs.readFile(path.resolve(__dirname, 'fixtures', 'wow.txt'), 'utf8')).should.include(
'WOW'
+49
View File
@@ -3,6 +3,55 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.0.18](https://github.com/appium/appium/compare/@appium/docutils@1.0.17...@appium/docutils@1.0.18) (2024-07-10)
### Bug Fixes
* **docutils:** update dependency typescript to v5.5.3 ([234ad59](https://github.com/appium/appium/commit/234ad597988be2560a63ba346dc5e4afbfb6e20d))
* **support:** update dependency teen_process to v2.1.10 ([86f843b](https://github.com/appium/appium/commit/86f843b9e1fc56576d7a08bf95838a58971e98b3))
* **support:** update dependency teen_process to v2.1.7 ([5226fa8](https://github.com/appium/appium/commit/5226fa897b90e9fec9be3e79a7d48fc7b4e0016d))
* **support:** update dependency teen_process to v2.2.0 ([06607da](https://github.com/appium/appium/commit/06607da92e93d015747fd6d6d5bdabe1b3ac58d2))
* **types:** update dependency type-fest to v4.21.0 ([#20335](https://github.com/appium/appium/issues/20335)) ([8894b9a](https://github.com/appium/appium/commit/8894b9adf709646108cc8d6426bbb690550609f2))
## [1.0.17](https://github.com/appium/appium/compare/@appium/docutils@1.0.16...@appium/docutils@1.0.17) (2024-06-28)
**Note:** Version bump only for package @appium/docutils
## [1.0.16](https://github.com/appium/appium/compare/@appium/docutils@1.0.15...@appium/docutils@1.0.16) (2024-06-27)
### Bug Fixes
* **docutils:** update dependency typescript to v5.5.2 ([189bce8](https://github.com/appium/appium/commit/189bce88a09c4b3146c48bedf6e8c1dcb50c3a6d))
* **support:** update dependency teen_process to v2.1.5 ([bc388db](https://github.com/appium/appium/commit/bc388db1116f411f4b241105f5feae30418c9a27))
* **support:** update dependency teen_process to v2.1.6 ([5412461](https://github.com/appium/appium/commit/541246184dc7521c825ec1902775e681ea6f0db3))
* **types:** update dependency type-fest to v4.20.1 ([#20255](https://github.com/appium/appium/issues/20255)) ([1984553](https://github.com/appium/appium/commit/19845531f558e2b16dfae807c768e1b9f2cab25d))
## [1.0.15](https://github.com/appium/appium/compare/@appium/docutils@1.0.14...@appium/docutils@1.0.15) (2024-06-11)
**Note:** Version bump only for package @appium/docutils
## [1.0.14](https://github.com/appium/appium/compare/@appium/docutils@1.0.13...@appium/docutils@1.0.14) (2024-06-11)
**Note:** Version bump only for package @appium/docutils
## [1.0.13](https://github.com/appium/appium/compare/@appium/docutils@1.0.12...@appium/docutils@1.0.13) (2024-06-11)
**Note:** Version bump only for package @appium/docutils
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/docutils",
"version": "1.0.13",
"version": "1.0.18",
"description": "Documentation generation utilities for Appium and related projects",
"keywords": [
"automation",
@@ -48,7 +48,7 @@
"start": "node ./build/lib/cli/index.js"
},
"dependencies": {
"@appium/support": "^5.0.1",
"@appium/support": "^5.1.2",
"@appium/tsconfig": "^0.3.3",
"@sliphua/lilconfig-ts-loader": "3.2.2",
"@types/which": "3.0.4",
@@ -62,9 +62,9 @@
"read-pkg": "5.2.0",
"semver": "7.6.2",
"source-map-support": "0.5.21",
"teen_process": "2.1.4",
"type-fest": "4.20.0",
"typescript": "5.4.5",
"teen_process": "2.2.0",
"type-fest": "4.21.0",
"typescript": "5.5.3",
"yaml": "2.4.5",
"yargs": "17.7.2",
"yargs-parser": "21.1.1"
+2 -2
View File
@@ -1,5 +1,5 @@
mkdocs==1.6.0
mkdocs-git-revision-date-localized-plugin==1.2.6
mkdocs-material==9.5.26
mkdocs-material==9.5.28
mkdocs-redirects==1.2.1
mike==2.1.1
mike==2.1.2
+5
View File
@@ -2,6 +2,11 @@ import {argify} from '../../lib/util';
import _ from 'lodash';
describe('argify', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
it('should create args from params', function () {
// deploy example
const version = '2.0';
+43
View File
@@ -3,6 +3,49 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.6.6](https://github.com/appium/appium/compare/@appium/driver-test-support@0.6.5...@appium/driver-test-support@0.6.6) (2024-07-10)
### Bug Fixes
* **types:** update dependency type-fest to v4.21.0 ([#20335](https://github.com/appium/appium/issues/20335)) ([8894b9a](https://github.com/appium/appium/commit/8894b9adf709646108cc8d6426bbb690550609f2))
## [0.6.5](https://github.com/appium/appium/compare/@appium/driver-test-support@0.6.4...@appium/driver-test-support@0.6.5) (2024-06-28)
### Bug Fixes
* **driver-test-support:** update dependency @types/lodash to v4.17.6 ([82e40c1](https://github.com/appium/appium/commit/82e40c1400e23f341c45d788982ccc5905827d7c))
## [0.6.4](https://github.com/appium/appium/compare/@appium/driver-test-support@0.6.3...@appium/driver-test-support@0.6.4) (2024-06-27)
### Bug Fixes
* **types:** update dependency type-fest to v4.20.1 ([#20255](https://github.com/appium/appium/issues/20255)) ([1984553](https://github.com/appium/appium/commit/19845531f558e2b16dfae807c768e1b9f2cab25d))
## [0.6.3](https://github.com/appium/appium/compare/@appium/driver-test-support@0.6.2...@appium/driver-test-support@0.6.3) (2024-06-11)
**Note:** Version bump only for package @appium/driver-test-support
## [0.6.2](https://github.com/appium/appium/compare/@appium/driver-test-support@0.6.1...@appium/driver-test-support@0.6.2) (2024-06-11)
**Note:** Version bump only for package @appium/driver-test-support
## [0.6.1](https://github.com/appium/appium/compare/@appium/driver-test-support@0.6.0...@appium/driver-test-support@0.6.1) (2024-06-11)
**Note:** Version bump only for package @appium/driver-test-support
+10 -6
View File
@@ -3,13 +3,9 @@ import {server, routeConfiguringFunction, DeviceSettings} from 'appium/driver';
import axios from 'axios';
import B from 'bluebird';
import {TEST_HOST, getTestPort, createAppiumURL} from './helpers';
import chai from 'chai';
import sinon from 'sinon';
import {Agent} from 'node:http';
const should = chai.should();
const {expect} = chai;
/**
* Creates some helper functions for E2E tests to manage sessions.
* @template [CommandData=unknown]
@@ -129,7 +125,16 @@ export function driverE2ETestSuite(DriverClass, defaultCaps = {}) {
let getCommand;
/** @type {SessionHelpers['postCommand']} */
let postCommand;
let expect;
let should;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
expect = chai.expect;
should = chai.should();
port = port ?? (await getTestPort());
defaultCaps = {...defaultCaps};
d = new DriverClass({port, address});
@@ -143,9 +148,8 @@ export function driverE2ETestSuite(DriverClass, defaultCaps = {}) {
({startSession, getSession, endSession, newSessionURL, getCommand, postCommand} =
createSessionHelpers(port, address));
});
after(async function () {
await baseServer.close();
await baseServer?.close();
});
describe('session handling', function () {
+12 -7
View File
@@ -2,11 +2,6 @@ import _ from 'lodash';
import B from 'bluebird';
import {createSandbox} from 'sinon';
import chai from 'chai';
const should = chai.should();
const {expect} = chai;
// wrap these tests in a function so we can export the tests and re-use them
// for actual driver implementations
@@ -31,6 +26,16 @@ export function driverUnitTestSuite(
let w3cCaps;
/** @type {import('sinon').SinonSandbox} */
let sandbox;
let expect;
let should;
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
expect = chai.expect;
should = chai.should();
});
beforeEach(function () {
sandbox = createSandbox();
@@ -45,8 +50,8 @@ export function driverUnitTestSuite(
};
});
afterEach(async function () {
sandbox.restore();
await d.deleteSession();
sandbox?.restore();
await d?.deleteSession();
});
describe('static property', function () {
+6 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/driver-test-support",
"version": "0.6.1",
"version": "0.6.6",
"description": "Test utilities for Appium drivers",
"keywords": [
"automation",
@@ -41,18 +41,19 @@
},
"types": "./build/lib/index.d.ts",
"dependencies": {
"@appium/types": "^0.20.1",
"@types/lodash": "4.17.5",
"@appium/types": "^0.21.1",
"@types/lodash": "4.17.6",
"@types/stoppable": "1.1.3",
"axios": "1.7.2",
"bluebird": "3.7.2",
"chai": "4.4.1",
"chai": "5.1.1",
"chai-as-promised": "8.0.0",
"get-port": "5.1.1",
"lodash": "4.17.21",
"sinon": "18.0.0",
"source-map-support": "0.5.21",
"stoppable": "1.1.0",
"type-fest": "4.20.0"
"type-fest": "4.21.0"
},
"peerDependencies": {
"appium": "^2.0.0-beta.43",

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