mirror of
https://github.com/appium/appium.git
synced 2026-11-01 14:58:00 +08:00
Compare commits
28
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
339acd345f | ||
|
|
21316e94d0 | ||
|
|
43fcc17b31 | ||
|
|
b1a4045bbd | ||
|
|
d2a8edbb7a | ||
|
|
6d67177e2f | ||
|
|
db62358dba | ||
|
|
4fd6893146 | ||
|
|
8915934270 | ||
|
|
ae7f74a014 | ||
|
|
ea9cf8d910 | ||
|
|
70449cd077 | ||
|
|
65c47acf59 | ||
|
|
96a7a3f23b | ||
|
|
c8f997973c | ||
|
|
bea47aacca | ||
|
|
10e5b37211 | ||
|
|
459f0a34b2 | ||
|
|
4c15dc6e5d | ||
|
|
848eb00afb | ||
|
|
de8b1c97dc | ||
|
|
092ebb2a69 | ||
|
|
dddc4aa8c0 | ||
|
|
425d3eac1d | ||
|
|
57b0406a33 | ||
|
|
e3e1757c56 | ||
|
|
17e271afff | ||
|
|
7718cd01d1 |
+20
-15
@@ -48,16 +48,6 @@ labels:
|
||||
matcher:
|
||||
files: ['packages/base-driver/**']
|
||||
|
||||
- label: '@appium/eslint-config-appium'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/eslint-config-appium/**']
|
||||
|
||||
- label: '@appium/eslint-config-appium-ts'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/eslint-config-appium-ts/**']
|
||||
|
||||
- label: '@appium/base-plugin'
|
||||
sync: true
|
||||
matcher:
|
||||
@@ -78,6 +68,16 @@ labels:
|
||||
matcher:
|
||||
files: ['packages/driver-test-support/**']
|
||||
|
||||
- label: '@appium/eslint-config-appium'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/eslint-config-appium/**']
|
||||
|
||||
- label: '@appium/eslint-config-appium-ts'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/eslint-config-appium-ts/**']
|
||||
|
||||
- label: '@appium/execute-driver-plugin'
|
||||
sync: true
|
||||
matcher:
|
||||
@@ -98,6 +98,11 @@ labels:
|
||||
matcher:
|
||||
files: ['packages/images-plugin/**']
|
||||
|
||||
- label: '@appium/logger'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/logger/**']
|
||||
|
||||
- label: '@appium/opencv'
|
||||
sync: true
|
||||
matcher:
|
||||
@@ -123,6 +128,11 @@ labels:
|
||||
matcher:
|
||||
files: ['packages/support/**']
|
||||
|
||||
- label: '@appium/strongbox'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/strongbox/**']
|
||||
|
||||
- label: '@appium/test-support'
|
||||
sync: true
|
||||
matcher:
|
||||
@@ -142,8 +152,3 @@ labels:
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/universal-xml-plugin/**']
|
||||
|
||||
- label: '@appium/strongbox'
|
||||
sync: true
|
||||
matcher:
|
||||
files: ['packages/strongbox/**']
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ Appium contains many different modules and supports a variety of drivers, plugin
|
||||
|
||||
## Main Appium Module
|
||||
|
||||
* ### [Appium 2.0 Changelog](packages/appium/CHANGELOG.md)
|
||||
* ### [Appium 2 Changelog](packages/appium/CHANGELOG.md)
|
||||
* [Appium 1.x Changelog](https://github.com/appium/appium/blob/1.x/CHANGELOG.md)
|
||||
|
||||
## Appium Drivers / Clients / Plugins
|
||||
@@ -23,6 +23,7 @@ Appium contains many different modules and supports a variety of drivers, plugin
|
||||
* [fake-driver](packages/fake-driver/CHANGELOG.md)
|
||||
* [fake-plugin](packages/fake-plugin/CHANGELOG.md)
|
||||
* [images-plugin](packages/images-plugin/CHANGELOG.md)
|
||||
* [logger](packages/logger/CHANGELOG.md)
|
||||
* [opencv](packages/opencv/CHANGELOG.md)
|
||||
* [plugin-test-support](packages/plugin-test-support/CHANGELOG.md)
|
||||
* [relaxed-caps-plugin](packages/relaxed-caps-plugin/CHANGELOG.md)
|
||||
@@ -31,6 +32,5 @@ Appium contains many different modules and supports a variety of drivers, plugin
|
||||
* [support](packages/support/CHANGELOG.md)
|
||||
* [test-support](packages/test-support/CHANGELOG.md)
|
||||
* [tsconfig](packages/tsconfig/CHANGELOG.md)
|
||||
* [typedoc-plugin-appium](packages/typedoc-plugin-appium/CHANGELOG.md)
|
||||
* [types](packages/types/CHANGELOG.md)
|
||||
* [universal-xml-plugin](packages/universal-xml-plugin/CHANGELOG.md)
|
||||
|
||||
+2
-2
@@ -83,7 +83,7 @@ related to contributions of funds. Both are extremely important to the ongoing h
|
||||
project. Financial sponsorship is mediated through our [OpenCollective page](https://opencollective.com/appium).
|
||||
Sponsorship tiers and benefits are described below:
|
||||
|
||||
- **Development Partners**: The primary need of any open source project is for sustained maintenance and contributorship. Companies that officially sponsor such development with dedicated employee time are recognized as Development Partners, and receive the same benefits as the highest tier of financial sponsorship. To be considered a Development Partner, a company must devote at least 50% of a full-time employee's time to Appium maintenance.
|
||||
- **Development Partners**: The primary need of any open source project is for sustained maintenance and contributorship. Companies that officially sponsor such development with dedicated employee time are recognized as Development Partners, and receive the same benefits as the highest tier of financial sponsorship. To be considered a Development Partner, a company must devote at least 50% of a full-time employee's time to Appium maintenance. This means that the contributors designated by the company must have been appointed as "committers" in good standing of one or more core Appium repositories. (See above for a description of how to become a committer).
|
||||
- **Strategic Partners**: Representing the highest tier of ongoing financial support for the project, Strategic Partners are what make our compensation scheme for contributors possible, and we thank them for their significant investment into the project! More than financial contribution, Strategic Partners help elevate Appium's position in the industry through marketing and evangelism efforts, and partner with the Appium team to help make Appium better. Along with the Development Partners, Strategic Partners have their logos displayed prominently on our website, and have the ability to link to their Appium-related products in a few relevant places in our documentation.
|
||||
- **Gold, Silver, and Bronze Sponsors**: these sponsorship levels correspond to different amounts of recurring financial contribution that generously support our contributor compensation scheme. Sponsors at these levels also have the opportunity to display their logo on our website.
|
||||
- **Backers**: individuals who benefit from the Appium project can also donate on a one-time or recurring basis, at any amount, and will be recognized as Backers for their contribution!
|
||||
@@ -91,7 +91,7 @@ Sponsorship tiers and benefits are described below:
|
||||
To become a sponsor at one of these levels, follow the process indicated at the [OpenCollective
|
||||
page](https://opencollective.com/appium).
|
||||
|
||||
### Compensation for TC Members, Committers, Contributors, and upstream projects
|
||||
### Compensation Scheme
|
||||
|
||||
With funds received through sponsorship, the Appium project wants to incentivize contributions of
|
||||
code, documentation efforts, maintenance, and project leadership. We have developed a scheme
|
||||
|
||||
@@ -178,8 +178,31 @@ cross-platform native app automation, for mobile and beyond!
|
||||
If you are looking for a more comprehensive description of what this is all about, please read our
|
||||
documentation on [How Does Appium Work?](https://appium.io/docs/en/latest/intro/appium/).
|
||||
|
||||
## Sponsors
|
||||
|
||||
Appium has a [Sponsorship Program](GOVERNANCE.md#sponsorship)! If you or your company uses Appium
|
||||
and wants to give back financially to the project, we use these funds to [encourage development and
|
||||
contributions](GOVERNANCE.md#compensation-scheme), as well as support other open source projects we
|
||||
rely on. [Become a sponsor](https://opencollective.com/appium) via our OpenCollective page.
|
||||
|
||||
### Development Partners
|
||||
|
||||
Appium is incredibly grateful to our Development Partners for their sustained contribution of
|
||||
project development and leadership!
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.headspin.io/solutions/appium-mobile-test-automation"><img src="packages/appium/docs/assets/images/sponsor-logo-headspin.png"
|
||||
width="300" alt="HeadSpin" /></a>
|
||||
</p>
|
||||
|
||||
### Other Sponsors
|
||||
|
||||
A full list of sponsors is available at our [Sponsors page](SPONSORS.md).
|
||||
|
||||
## License
|
||||
|
||||
[Apache-2.0](./LICENSE)
|
||||
|
||||
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fappium%2Fappium?ref=badge_large)
|
||||
|
||||
`@appium/logger` package is under [ISC](./packages/logger/LICENSE) License.
|
||||
|
||||
+11
-5
@@ -11,7 +11,8 @@ Hub](https://opencollective.com/appium).
|
||||
We are very grateful for the support of our Development Partners, who donate Appium development and
|
||||
maintenance as part of their employees' core job duties!
|
||||
|
||||
* *Coming Soon!*
|
||||
<a href="https://www.headspin.io/solutions/appium-mobile-test-automation" target="_blank"><img
|
||||
src="packages/appium/docs/assets/images/sponsor-logo-headspin.png" width="250"/></a>
|
||||
|
||||
## Strategic Partners
|
||||
|
||||
@@ -23,13 +24,18 @@ contributors!
|
||||
|
||||
## Gold Sponsors
|
||||
|
||||
* [Become a Gold Sponsor](https://opencollective.com/appium/contribute/gold-sponsor-72877/checkout?interval=month&amount=500&contributeAs=me)
|
||||
<a href="https://opencollective.com/appium" target="_blank"><img src="https://opencollective.com/appium/tiers/gold-sponsor.svg?avatarHeight=100&button=false"/></a>
|
||||
|
||||
[Become a Gold Sponsor](https://opencollective.com/appium/contribute/gold-sponsor-72877/checkout?interval=month&amount=500&contributeAs=me)
|
||||
|
||||
## Silver Sponsors
|
||||
|
||||
* [Become a Silver Sponsor](https://opencollective.com/appium/contribute/silver-sponsor-72876/checkout?interval=month&amount=250&contributeAs=me)
|
||||
<a href="https://opencollective.com/appium" target="_blank"><img src="https://opencollective.com/appium/tiers/silver-sponsor.svg?avatarHeight=80&button=false"/></a>
|
||||
|
||||
[Become a Silver Sponsor](https://opencollective.com/appium/contribute/silver-sponsor-72876/checkout?interval=month&amount=250&contributeAs=me)
|
||||
|
||||
## Bronze Sponsors
|
||||
|
||||
- [MagicPod](https://magicpod.com/en/)
|
||||
* [Become a Bronze Sponsor](https://opencollective.com/appium/contribute/sponsors-70690/checkout?interval=month&amount=100&contributeAs=me)
|
||||
<a href="https://opencollective.com/appium" target="_blank"><img src="https://opencollective.com/appium/tiers/sponsors.svg?avatarHeight=60&button=false"/></a>
|
||||
|
||||
[Become a Bronze Sponsor](https://opencollective.com/appium/contribute/sponsors-70690/checkout?interval=month&amount=100&contributeAs=me)
|
||||
|
||||
Generated
+463
-681
File diff suppressed because it is too large
Load Diff
+8
-8
@@ -86,7 +86,7 @@
|
||||
"@types/chai-as-promised": "7.1.8",
|
||||
"@types/diff": "5.2.1",
|
||||
"@types/mocha": "10.0.6",
|
||||
"@types/node": "20.12.12",
|
||||
"@types/node": "20.14.2",
|
||||
"@types/semver": "7.5.8",
|
||||
"@types/sinon": "17.0.3",
|
||||
"@types/sinon-chai": "3.2.12",
|
||||
@@ -94,8 +94,8 @@
|
||||
"@types/teen_process": "2.0.4",
|
||||
"@types/ws": "8.5.10",
|
||||
"@types/yargs": "17.0.32",
|
||||
"@typescript-eslint/eslint-plugin": "7.10.0",
|
||||
"@typescript-eslint/parser": "7.10.0",
|
||||
"@typescript-eslint/eslint-plugin": "7.12.0",
|
||||
"@typescript-eslint/parser": "7.12.0",
|
||||
"asyncbox": "3.0.0",
|
||||
"chai": "4.4.1",
|
||||
"chai-as-promised": "7.1.2",
|
||||
@@ -112,7 +112,7 @@
|
||||
"fancy-log": "2.0.0",
|
||||
"finalhandler": "1.2.0",
|
||||
"get-port": "5.1.1",
|
||||
"json-schema-to-typescript": "14.0.4",
|
||||
"json-schema-to-typescript": "14.0.5",
|
||||
"lerna": "8.1.3",
|
||||
"log-symbols": "4.1.0",
|
||||
"midnight-smoker": "8.0.0",
|
||||
@@ -121,7 +121,7 @@
|
||||
"mocha": "10.4.0",
|
||||
"mocha-chai-jest-snapshot": "1.1.4",
|
||||
"npm-run-all2": "6.2.0",
|
||||
"prettier": "3.2.5",
|
||||
"prettier": "3.3.1",
|
||||
"rewiremock": "3.14.5",
|
||||
"rimraf": "5.0.7",
|
||||
"serve-static": "1.15.0",
|
||||
@@ -133,7 +133,7 @@
|
||||
"tsd": "0.31.0",
|
||||
"typescript": "5.4.5",
|
||||
"validate.js": "0.13.1",
|
||||
"webdriverio": "8.38.0",
|
||||
"webdriverio": "8.38.2",
|
||||
"ws": "8.17.0",
|
||||
"yaml-js": "0.3.1"
|
||||
},
|
||||
@@ -146,10 +146,10 @@
|
||||
},
|
||||
"overrides": {
|
||||
"@sidvind/better-ajv-errors": {
|
||||
"ajv": "8.14.0"
|
||||
"ajv": "8.16.0"
|
||||
},
|
||||
"ajv-formats": {
|
||||
"ajv": "8.14.0"
|
||||
"ajv": "8.16.0"
|
||||
},
|
||||
"http-cache-semantics": "4.1.1"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,26 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.7.0](https://github.com/appium/appium/compare/appium@2.6.0...appium@2.7.0) (2024-06-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **appium:** Replace npmlog with the local fork ([#20190](https://github.com/appium/appium/issues/20190)) ([8915934](https://github.com/appium/appium/commit/8915934270243bfb46c4d104a098ce1cc481b0ff))
|
||||
* **base-driver:** Make addition of search query params to cache optional ([#20195](https://github.com/appium/appium/issues/20195)) ([21316e9](https://github.com/appium/appium/commit/21316e94d05b2f97aa0349a82da229713e92446c))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **appium:** ensure ws close code is valid ([#20178](https://github.com/appium/appium/issues/20178)) ([65c47ac](https://github.com/appium/appium/commit/65c47acf5954bbf1947e896ef79c81a9b3c712a5))
|
||||
* **appium:** update dependency ajv to v8.16.0 ([ae7f74a](https://github.com/appium/appium/commit/ae7f74a0144d233653443622a84d49b1cb4e6222))
|
||||
* **docutils:** update dependency yaml to v2.4.3 ([848eb00](https://github.com/appium/appium/commit/848eb00afbd1cab76a6a1c3d0f4a2a0b1acee0d0))
|
||||
* **execute-driver-plugin:** update dependency webdriverio to v8.38.2 ([c8f9979](https://github.com/appium/appium/commit/c8f997973cc21673f95d02c92d43a2981b8713b8))
|
||||
* **support:** update dependency teen_process to v2.1.4 ([96a7a3f](https://github.com/appium/appium/commit/96a7a3f23bead7c1d18700550138cd2d70ce5e3c))
|
||||
* **types:** update dependency type-fest to v4.19.0 ([#20193](https://github.com/appium/appium/issues/20193)) ([db62358](https://github.com/appium/appium/commit/db62358dbac25de2a75fdc7493338d98b1422c84))
|
||||
|
||||
|
||||
|
||||
## [2.6.0](https://github.com/appium/appium/compare/appium@2.5.4...appium@2.6.0) (2024-05-27)
|
||||
|
||||
|
||||
|
||||
@@ -178,8 +178,31 @@ cross-platform native app automation, for mobile and beyond!
|
||||
If you are looking for a more comprehensive description of what this is all about, please read our
|
||||
documentation on [How Does Appium Work?](https://appium.io/docs/en/latest/intro/appium/).
|
||||
|
||||
## Sponsors
|
||||
|
||||
Appium has a [Sponsorship Program](GOVERNANCE.md#sponsorship)! If you or your company uses Appium
|
||||
and wants to give back financially to the project, we use these funds to [encourage development and
|
||||
contributions](GOVERNANCE.md#compensation-scheme), as well as support other open source projects we
|
||||
rely on. [Become a sponsor](https://opencollective.com/appium) via our OpenCollective page.
|
||||
|
||||
### Development Partners
|
||||
|
||||
Appium is incredibly grateful to our Development Partners for their sustained contribution of
|
||||
project development and leadership!
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.headspin.io/solutions/appium-mobile-test-automation"><img src="packages/appium/docs/assets/images/sponsor-logo-headspin.png"
|
||||
width="300" alt="HeadSpin" /></a>
|
||||
</p>
|
||||
|
||||
### Other Sponsors
|
||||
|
||||
A full list of sponsors is available at our [Sponsors page](SPONSORS.md).
|
||||
|
||||
## License
|
||||
|
||||
[Apache-2.0](./LICENSE)
|
||||
|
||||
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fappium%2Fappium?ref=badge_large)
|
||||
|
||||
`@appium/logger` package is under [ISC](./packages/logger/LICENSE) License.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -4,3 +4,15 @@
|
||||
.md-source__fact:nth-child(1n + 2):before {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
.appium-sponsor-thanks {
|
||||
width: 100%;
|
||||
margin: auto 0.6rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.appium-sponsor-thanks img {
|
||||
margin: auto 6px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ copyright: Copyright © 2012 OpenJS Foundation - <a href="#__consent">Change
|
||||
theme:
|
||||
logo: assets/images/appium-logo-white.png
|
||||
favicon: assets/images/appium-logo.png
|
||||
custom_dir: overrides
|
||||
|
||||
plugins:
|
||||
blog:
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
authors:
|
||||
- jlipps
|
||||
date: 2024-06-06
|
||||
---
|
||||
|
||||
# Announcing HeadSpin as Appium's Development Partner
|
||||
|
||||
Recently, we announced a new [sponsorship and contributor compensation program](https://appium.io/docs/en/latest/blog/2024/05/14/announcing-appiums-sponsorship-program/) for the Appium
|
||||
project. As part of this program, we felt it was important to have a place to recognize those
|
||||
companies who make an extremely valuable kind of contribution to the project: dedicated maintainer
|
||||
time. Appium only survives because of the tireless efforts of the core maintainers, and some of us
|
||||
are only able to do this work because it is donated on behalf of our day jobs. We're therefore very
|
||||
excited to announce our first Development Partner: <a
|
||||
href="https://www.headspin.io/solutions/appium-mobile-test-automation">HeadSpin</a>!
|
||||
|
||||
<!-- more -->
|
||||
|
||||
<div style="text-align:center;width:100%">
|
||||
<a href="https://www.headspin.io/solutions/appium-mobile-test-automation"><img
|
||||
src="/docs/en/assets/images/sponsor-logo-headspin.png" style="width: 300px"/></a>
|
||||
</div>
|
||||
|
||||
HeadSpin is a real device performance and UX analysis cloud, with full support for Appium. When you
|
||||
run your Appium tests on HeadSpin, you get access to comprehensive performance reports about your
|
||||
app, including potential network, system resource, or user experience issues. HeadSpin supports
|
||||
a variety of complex testing modes, including hooking up your own devices to the cloud, injecting
|
||||
and receiving video and audio to/from devices, working with media (streaming) platforms, and more.
|
||||
|
||||
HeadSpin has been one of the Appium project's biggest supporters for a long time, and currently
|
||||
employs two of Appium's core maintainers, donating a significant portion of their time towards the
|
||||
development, maintenance, support, and leadership of open source Appium repos. HeadSpin has also
|
||||
worked hard towards Appium's vision of a robust Appium ecosystem, contributing several
|
||||
HeadSpin-maintained Appium drivers and plugins to the community:
|
||||
|
||||
- A [Roku TV driver](https://github.com/headspinio/appium-roku-driver)
|
||||
- A [Tizen TV driver](https://github.com/headspinio/appium-tizen-tv-driver/)
|
||||
- A [LG webOS TV driver](https://github.com/headspinio/appium-lg-webos-driver/)
|
||||
- A [Unity game automation plugin](https://github.com/headspinio/appium-altunity-plugin)
|
||||
|
||||
These are all free and open source Appium components that HeadSpin has donated to the community
|
||||
with the goal of fostering collaboration in these areas of media app automation.
|
||||
|
||||
Looking to the future, HeadSpin plans to continue supporting Appium in significant ways, both as
|
||||
a Development Partner and a significant contributor to the Appium ecosystem. The Appium project is
|
||||
deeply indebted to HeadSpin for all of its support, and is proud to take this moment to recognize
|
||||
HeadSpin as our first official Development Partner!
|
||||
@@ -21,3 +21,6 @@ environment variables that the Appium server understands:
|
||||
|`APPIUM_OMIT_PEER_DEPS`|Adds `--omit=peer` to all the NPM commands run internally by Appium. Mostly an internal feature.|
|
||||
|`APPIUM_APPS_CACHE_MAX_AGE`|Allows to set the maximum age (in minutes) for [cached applications](../guides/caching.md). The default value is `60 * 24` (24 hours). Do not set it to a lower number than the duration of a single session startup.|
|
||||
|`APPIUM_APPS_CACHE_MAX_ITEMS`|Allows to set the maximum amount of [cached applications](../guides/caching.md). The default value is `1024`. Do not set it to a lower number than the amount of apps in all parallel sessions per process.|
|
||||
|`APPIUM_APPS_CACHE_IGNORE_URL_QUERY`| If the above option is enabled then the 'search' part of the app URL will be cut off from cache keys. See the corresponding
|
||||
[feature request](https://discuss.appium.io/t/regarding-app-caching-when-using-aws-s3-presigned-urls/42713)
|
||||
for more details. Disabled by default.|
|
||||
|
||||
@@ -63,6 +63,11 @@ of it. It is a [LRU Cache](https://www.npmjs.com/package/lru-cache) with the fol
|
||||
[APPIUM_APPS_CACHE_MAX_AGE](../cli/env-vars.md) environment variable.
|
||||
Do not set it to a lower number than the duration of a single session startup.
|
||||
- TTL is refreshed for each entry upon access
|
||||
- By default the full application URL is used as cache key. You may change this behavior
|
||||
by enabling the [APPIUM_APPS_CACHE_IGNORE_URL_QUERY](../cli/env-vars.md) environment variable.
|
||||
If the above option is enabled then the 'search' part of the app URL will be cut off from cache keys.
|
||||
See the corresponding [feature request](https://discuss.appium.io/t/regarding-app-caching-when-using-aws-s3-presigned-urls/42713)
|
||||
for more details.
|
||||
|
||||
!!! warning
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ hide:
|
||||
title: Welcome
|
||||
---
|
||||
<style>
|
||||
.md-typeset h1 {
|
||||
.md-typeset h1,
|
||||
.appium-sponsor-thanks {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -19,6 +20,17 @@ software, designed to facilitate UI automation of many app platforms, including
|
||||
Android, Tizen), browser (Chrome, Firefox, Safari), desktop (macOS, Windows), TV (Roku, tvOS,
|
||||
Android TV, Samsung), and more!
|
||||
|
||||
|
||||
<div style="text-align: center">
|
||||
Appium is extremely grateful for the support of its key partners! (Learn more about our
|
||||
sponsorship program and contributor compensation scheme
|
||||
<a href="https://github.com/appium/appium/blob/master/GOVERNANCE.md#sponsorship">here</a>)
|
||||
<br/>
|
||||
<a href="https://www.headspin.io/solutions/appium-mobile-test-automation">
|
||||
<img src="assets/images/sponsor-logo-headspin.png" style="width: 200px;" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## Explore the Documentation
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
<!-- Footer -->
|
||||
<footer class="md-footer">
|
||||
|
||||
<!-- Link to previous and/or next page -->
|
||||
{% if "navigation.footer" in features %}
|
||||
{% if page.previous_page or page.next_page %}
|
||||
{% if page.meta and page.meta.hide %}
|
||||
{% set hidden = "hidden" if "footer" in page.meta.hide %}
|
||||
{% endif %}
|
||||
<nav
|
||||
class="md-footer__inner md-grid"
|
||||
aria-label="{{ lang.t('footer') }}"
|
||||
{{ hidden }}
|
||||
>
|
||||
|
||||
<!-- Link to previous page -->
|
||||
{% if page.previous_page %}
|
||||
{% set direction = lang.t("footer.previous") %}
|
||||
<a
|
||||
href="{{ page.previous_page.url | url }}"
|
||||
class="md-footer__link md-footer__link--prev"
|
||||
aria-label="{{ direction }}: {{ page.previous_page.title | e }}"
|
||||
>
|
||||
<div class="md-footer__button md-icon">
|
||||
{% set icon = config.theme.icon.previous or "material/arrow-left" %}
|
||||
{% include ".icons/" ~ icon ~ ".svg" %}
|
||||
</div>
|
||||
<div class="md-footer__title">
|
||||
<span class="md-footer__direction">
|
||||
{{ direction }}
|
||||
</span>
|
||||
<div class="md-ellipsis">
|
||||
{{ page.previous_page.title }}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<!-- Link to next page -->
|
||||
{% if page.next_page %}
|
||||
{% set direction = lang.t("footer.next") %}
|
||||
<a
|
||||
href="{{ page.next_page.url | url }}"
|
||||
class="md-footer__link md-footer__link--next"
|
||||
aria-label="{{ direction }}: {{ page.next_page.title | e }}"
|
||||
>
|
||||
<div class="md-footer__title">
|
||||
<span class="md-footer__direction">
|
||||
{{ direction }}
|
||||
</span>
|
||||
<div class="md-ellipsis">
|
||||
{{ page.next_page.title }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="md-footer__button md-icon">
|
||||
{% set icon = config.theme.icon.next or "material/arrow-right" %}
|
||||
{% include ".icons/" ~ icon ~ ".svg" %}
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<!-- Further information -->
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<!-- Sponsor thanks -->
|
||||
{% include "partials/sponsors.html" %}
|
||||
|
||||
{% include "partials/copyright.html" %}
|
||||
|
||||
<!-- Social links -->
|
||||
{% if config.extra.social %}
|
||||
{% include "partials/social.html" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -0,0 +1,6 @@
|
||||
<div class="appium-sponsor-thanks">
|
||||
Supported by
|
||||
<a href="https://www.headspin.io/solutions/appium-mobile-test-automation">
|
||||
<img src="/docs/en/assets/images/sponsor-logo-headspin.png" />
|
||||
</a>
|
||||
</div>
|
||||
@@ -21,6 +21,10 @@ import {getDefaultsForExtension} from './schema';
|
||||
import {DRIVER_TYPE, BIDI_BASE_PATH, BIDI_EVENT_NAME} from './constants';
|
||||
import WebSocket from 'ws';
|
||||
|
||||
const MIN_WS_CODE_VAL = 1000;
|
||||
const MAX_WS_CODE_VAL = 1015;
|
||||
const WS_FALLBACK_CODE = 1011; // server encountered an error while fulfilling request
|
||||
|
||||
const desiredCapabilityConstraints = /** @type {const} */ ({
|
||||
automationName: {
|
||||
presence: true,
|
||||
@@ -418,6 +422,16 @@ class AppiumDriver extends DriverCore {
|
||||
`Upstream bidi socket closed connection (code ${code}, reason: '${reason}'). ` +
|
||||
`Closing proxy connection to client`,
|
||||
);
|
||||
if (!_.isNumber(code)) {
|
||||
code = parseInt(code, 10);
|
||||
}
|
||||
if (_.isNaN(code) || code < MIN_WS_CODE_VAL || code > MAX_WS_CODE_VAL) {
|
||||
this.log.warn(
|
||||
`Received code ${code} from upstream socket, but this is not a valid ` +
|
||||
`websocket code. Rewriting to ${WS_FALLBACK_CODE} for ws compatibility`,
|
||||
);
|
||||
code = WS_FALLBACK_CODE;
|
||||
}
|
||||
ws.close(code, reason);
|
||||
});
|
||||
|
||||
@@ -1106,7 +1120,7 @@ class AppiumDriver extends DriverCore {
|
||||
}
|
||||
|
||||
// here we know that we are executing a session command, and have a valid session driver
|
||||
return await (/** @type {any} */ (dstSession)).executeCommand(cmd, ...args);
|
||||
return await /** @type {any} */ (dstSession).executeCommand(cmd, ...args);
|
||||
};
|
||||
|
||||
// now take our default behavior, wrap it with any number of plugin behaviors, and run it
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import npmlog from 'npmlog';
|
||||
import globalLog from '@appium/logger';
|
||||
import {createLogger, format, transports} from 'winston';
|
||||
import {fs, logger} from '@appium/support';
|
||||
import { APPIUM_LOGGER_NAME } from './logger';
|
||||
import _ from 'lodash';
|
||||
|
||||
// set up distributed logging before everything else
|
||||
logger.patchLogger(npmlog);
|
||||
global._global_npmlog = npmlog;
|
||||
logger.patchLogger(globalLog);
|
||||
global._global_npmlog = globalLog;
|
||||
|
||||
// npmlog is used only for emitting, we use winston for output
|
||||
npmlog.level = 'info';
|
||||
globalLog.level = 'info';
|
||||
const levels = {
|
||||
debug: 4,
|
||||
info: 3,
|
||||
@@ -198,7 +198,7 @@ function getColorizedPrefix(prefix) {
|
||||
}
|
||||
|
||||
async function init(args) {
|
||||
npmlog.level = 'silent';
|
||||
globalLog.level = 'silent';
|
||||
|
||||
// set de facto param passed to timestamp function
|
||||
useLocalTimeZone = args.localTimezone;
|
||||
@@ -215,7 +215,7 @@ async function init(args) {
|
||||
|
||||
const reportedLoggerErrors = new Set();
|
||||
// Capture logs emitted via npmlog and pass them through winston
|
||||
npmlog.on('log', ({level, message, prefix}) => {
|
||||
globalLog.on('log', ({level, message, prefix}) => {
|
||||
const winstonLevel = npmToWinstonLevels[level] || 'info';
|
||||
let msg = message;
|
||||
if (prefix) {
|
||||
@@ -249,7 +249,7 @@ function clear() {
|
||||
log.remove(transport);
|
||||
}
|
||||
}
|
||||
npmlog.removeAllListeners('log');
|
||||
globalLog.removeAllListeners('log');
|
||||
}
|
||||
|
||||
export {init, clear};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "appium",
|
||||
"version": "2.6.0",
|
||||
"version": "2.7.0",
|
||||
"description": "Automation for Apps.",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -60,12 +60,12 @@
|
||||
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@appium/base-driver": "^9.7.0",
|
||||
"@appium/base-plugin": "^2.2.32",
|
||||
"@appium/docutils": "^1.0.8",
|
||||
"@appium/base-driver": "^9.8.0",
|
||||
"@appium/base-plugin": "^2.2.33",
|
||||
"@appium/docutils": "^1.0.9",
|
||||
"@appium/schema": "~0.5.0",
|
||||
"@appium/support": "^4.2.6",
|
||||
"@appium/types": "^0.18.0",
|
||||
"@appium/support": "^4.3.0",
|
||||
"@appium/types": "^0.19.0",
|
||||
"@sidvind/better-ajv-errors": "2.1.3",
|
||||
"@types/argparse": "2.0.16",
|
||||
"@types/bluebird": "3.5.42",
|
||||
@@ -73,7 +73,7 @@
|
||||
"@types/semver": "7.5.8",
|
||||
"@types/teen_process": "2.0.4",
|
||||
"@types/wrap-ansi": "3.0.0",
|
||||
"ajv": "8.14.0",
|
||||
"ajv": "8.16.0",
|
||||
"ajv-formats": "3.0.1",
|
||||
"argparse": "2.0.1",
|
||||
"async-lock": "1.4.1",
|
||||
@@ -83,18 +83,17 @@
|
||||
"cross-env": "7.0.3",
|
||||
"lilconfig": "3.1.1",
|
||||
"lodash": "4.17.21",
|
||||
"npmlog": "7.0.1",
|
||||
"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.3",
|
||||
"type-fest": "4.18.3",
|
||||
"teen_process": "2.1.4",
|
||||
"type-fest": "4.19.0",
|
||||
"winston": "3.13.0",
|
||||
"wrap-ansi": "7.0.0",
|
||||
"ws": "8.17.0",
|
||||
"yaml": "2.4.2"
|
||||
"yaml": "2.4.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"webdriverio": "8.38.0"
|
||||
"webdriverio": "8.38.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,20 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [9.8.0](https://github.com/appium/appium/compare/@appium/base-driver@9.7.0...@appium/base-driver@9.8.0) (2024-06-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **base-driver:** Make addition of search query params to cache optional ([#20195](https://github.com/appium/appium/issues/20195)) ([21316e9](https://github.com/appium/appium/commit/21316e94d05b2f97aa0349a82da229713e92446c))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **types:** update dependency type-fest to v4.19.0 ([#20193](https://github.com/appium/appium/issues/20193)) ([db62358](https://github.com/appium/appium/commit/db62358dbac25de2a75fdc7493338d98b1422c84))
|
||||
|
||||
|
||||
|
||||
## [9.7.0](https://github.com/appium/appium/compare/@appium/base-driver@9.6.0...@appium/base-driver@9.7.0) (2024-05-27)
|
||||
|
||||
|
||||
|
||||
@@ -61,74 +61,6 @@ process.on('exit', () => {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} [envVarName]
|
||||
* @param {number} defaultValue
|
||||
* @returns {number}
|
||||
*/
|
||||
function toNaturalNumber(defaultValue, envVarName) {
|
||||
if (!envVarName || _.isUndefined(process.env[envVarName])) {
|
||||
return defaultValue;
|
||||
}
|
||||
const num = parseInt(`${process.env[envVarName]}`, 10);
|
||||
return num > 0 ? num : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} app
|
||||
* @param {string[]} supportedAppExtensions
|
||||
* @returns {string}
|
||||
*/
|
||||
function verifyAppExtension(app, supportedAppExtensions) {
|
||||
if (supportedAppExtensions.map(_.toLower).includes(_.toLower(path.extname(app)))) {
|
||||
return app;
|
||||
}
|
||||
throw new Error(
|
||||
`New app path '${app}' did not have ` +
|
||||
`${util.pluralize('extension', supportedAppExtensions.length, false)}: ` +
|
||||
supportedAppExtensions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} folderPath
|
||||
* @returns {Promise<number>}
|
||||
*/
|
||||
async function calculateFolderIntegrity(folderPath) {
|
||||
return (await fs.glob('**/*', {cwd: folderPath})).length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} filePath
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
async function calculateFileIntegrity(filePath) {
|
||||
return await fs.hash(filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} currentPath
|
||||
* @param {import('@appium/types').StringRecord} expectedIntegrity
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async function isAppIntegrityOk(currentPath, expectedIntegrity = {}) {
|
||||
if (!(await fs.exists(currentPath))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Folder integrity check is simple:
|
||||
// Verify the previous amount of files is not greater than the current one.
|
||||
// We don't want to use equality comparison because of an assumption that the OS might
|
||||
// create some unwanted service files/cached inside of that folder or its subfolders.
|
||||
// Ofc, validating the hash sum of each file (or at least of file path) would be much
|
||||
// more precise, but we don't need to be very precise here and also don't want to
|
||||
// overuse RAM and have a performance drop.
|
||||
return (await fs.stat(currentPath)).isDirectory()
|
||||
? (await calculateFolderIntegrity(currentPath)) >= expectedIntegrity?.folder
|
||||
: (await calculateFileIntegrity(currentPath)) === expectedIntegrity?.file;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} app
|
||||
@@ -171,15 +103,16 @@ export async function configureApp(
|
||||
maxAge: null,
|
||||
etag: null,
|
||||
};
|
||||
const {protocol, pathname} = url.parse(newApp);
|
||||
const isUrl = protocol === null ? false : ['http:', 'https:'].includes(protocol);
|
||||
const {protocol, pathname} = parseAppLink(app);
|
||||
const isUrl = isSupportedUrl(app);
|
||||
const appCacheKey = toCacheKey(app);
|
||||
|
||||
const cachedAppInfo = APPLICATIONS_CACHE.get(app);
|
||||
const cachedAppInfo = APPLICATIONS_CACHE.get(appCacheKey);
|
||||
if (cachedAppInfo) {
|
||||
logger.debug(`Cached app data: ${JSON.stringify(cachedAppInfo, null, 2)}`);
|
||||
}
|
||||
|
||||
return await APPLICATIONS_CACHE_GUARD.acquire(app, async () => {
|
||||
return await APPLICATIONS_CACHE_GUARD.acquire(appCacheKey, async () => {
|
||||
if (isUrl) {
|
||||
// Use the app from remote URL
|
||||
logger.info(`Using downloadable app '${newApp}'`);
|
||||
@@ -223,7 +156,7 @@ export async function configureApp(
|
||||
`The application at '${cachedAppInfo.fullPath}' does not exist anymore ` +
|
||||
`or its integrity has been damaged. Deleting it from the internal cache`
|
||||
);
|
||||
APPLICATIONS_CACHE.delete(app);
|
||||
APPLICATIONS_CACHE.delete(appCacheKey);
|
||||
|
||||
if (!stream.closed) {
|
||||
stream.destroy();
|
||||
@@ -332,7 +265,7 @@ export async function configureApp(
|
||||
`The application at '${fullPath}' does not exist anymore ` +
|
||||
`or its integrity has been damaged. Deleting it from the cache`
|
||||
);
|
||||
APPLICATIONS_CACHE.delete(app);
|
||||
APPLICATIONS_CACHE.delete(appCacheKey);
|
||||
}
|
||||
const tmpRoot = await tempDir.openDir();
|
||||
try {
|
||||
@@ -363,7 +296,7 @@ export async function configureApp(
|
||||
} else {
|
||||
integrity.file = await calculateFileIntegrity(appPathToCache);
|
||||
}
|
||||
APPLICATIONS_CACHE.set(app, {
|
||||
APPLICATIONS_CACHE.set(appCacheKey, {
|
||||
...remoteAppProps,
|
||||
timestamp: Date.now(),
|
||||
packageHash,
|
||||
@@ -389,12 +322,94 @@ export async function configureApp(
|
||||
}
|
||||
|
||||
verifyAppExtension(newApp, supportedAppExtensions);
|
||||
return app !== newApp && (packageHash || _.values(remoteAppProps).some(Boolean))
|
||||
return appCacheKey !== toCacheKey(newApp) && (packageHash || _.values(remoteAppProps).some(Boolean))
|
||||
? await storeAppInCache(newApp)
|
||||
: newApp;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} app
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isPackageOrBundle(app) {
|
||||
return /^([a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+)+$/.test(app);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all instances 'firstKey' and create a duplicate with the key 'secondKey',
|
||||
* Do the same thing in reverse. If we find 'secondKey', create a duplicate with the key 'firstKey'.
|
||||
*
|
||||
* This will cause keys to be overwritten if the object contains 'firstKey' and 'secondKey'.
|
||||
|
||||
* @param {*} input Any type of input
|
||||
* @param {String} firstKey The first key to duplicate
|
||||
* @param {String} secondKey The second key to duplicate
|
||||
*/
|
||||
export function duplicateKeys(input, firstKey, secondKey) {
|
||||
// If array provided, recursively call on all elements
|
||||
if (_.isArray(input)) {
|
||||
return input.map((item) => duplicateKeys(item, firstKey, secondKey));
|
||||
}
|
||||
|
||||
// If object, create duplicates for keys and then recursively call on values
|
||||
if (_.isPlainObject(input)) {
|
||||
const resultObj = {};
|
||||
for (let [key, value] of _.toPairs(input)) {
|
||||
const recursivelyCalledValue = duplicateKeys(value, firstKey, secondKey);
|
||||
if (key === firstKey) {
|
||||
resultObj[secondKey] = recursivelyCalledValue;
|
||||
} else if (key === secondKey) {
|
||||
resultObj[firstKey] = recursivelyCalledValue;
|
||||
}
|
||||
resultObj[key] = recursivelyCalledValue;
|
||||
}
|
||||
return resultObj;
|
||||
}
|
||||
|
||||
// Base case. Return primitives without doing anything.
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a desired capability and tries to JSON.parse it as an array,
|
||||
* and either returns the parsed array or a singleton array.
|
||||
*
|
||||
* @param {string|Array<String>} cap A desired capability
|
||||
*/
|
||||
export function parseCapsArray(cap) {
|
||||
if (_.isArray(cap)) {
|
||||
return cap;
|
||||
}
|
||||
|
||||
let parsedCaps;
|
||||
try {
|
||||
parsedCaps = JSON.parse(cap);
|
||||
if (_.isArray(parsedCaps)) {
|
||||
return parsedCaps;
|
||||
}
|
||||
} catch (ign) {
|
||||
logger.warn(`Failed to parse capability as JSON array`);
|
||||
}
|
||||
if (_.isString(cap)) {
|
||||
return [cap];
|
||||
}
|
||||
throw new Error(`must provide a string or JSON Array; received ${cap}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a string that uniquely describes driver instance
|
||||
*
|
||||
* @param {import('@appium/types').Core} obj driver instance
|
||||
* @param {string?} sessionId session identifier (if exists)
|
||||
* @returns {string}
|
||||
*/
|
||||
export function generateDriverLogPrefix(obj, sessionId = null) {
|
||||
const instanceName = `${obj.constructor.name}@${node.getObjectId(obj).substring(0, 4)}`;
|
||||
return sessionId ? `${instanceName} (${sessionId.substring(0, 8)})` : instanceName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends a HTTP GET query to fetch the app with caching enabled.
|
||||
* Follows https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching
|
||||
@@ -500,9 +515,7 @@ async function unzipApp(zipPath, dstRoot, supportedAppExtensions) {
|
||||
try {
|
||||
logger.debug(`Unzipping '${zipPath}'`);
|
||||
const timer = new timing.Timer().start();
|
||||
const useSystemUnzipEnv = process.env.APPIUM_PREFER_SYSTEM_UNZIP;
|
||||
const useSystemUnzip =
|
||||
_.isEmpty(useSystemUnzipEnv) || !['0', 'false'].includes(_.toLower(useSystemUnzipEnv));
|
||||
const useSystemUnzip = isEnvOptionEnabled('APPIUM_PREFER_SYSTEM_UNZIP', true);
|
||||
/**
|
||||
* Attempt to use use the system `unzip` (e.g., `/usr/bin/unzip`) due
|
||||
* to the significant performance improvement it provides over the native
|
||||
@@ -556,84 +569,144 @@ async function unzipApp(zipPath, dstRoot, supportedAppExtensions) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} app
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isPackageOrBundle(app) {
|
||||
return /^([a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+)+$/.test(app);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all instances 'firstKey' and create a duplicate with the key 'secondKey',
|
||||
* Do the same thing in reverse. If we find 'secondKey', create a duplicate with the key 'firstKey'.
|
||||
* Transforms the given app link to the cache key.
|
||||
* This is necessary to properly cache apps
|
||||
* having the same address, but different query strings,
|
||||
* for example ones stored in S3 using presigned URLs.
|
||||
*
|
||||
* This will cause keys to be overwritten if the object contains 'firstKey' and 'secondKey'.
|
||||
|
||||
* @param {*} input Any type of input
|
||||
* @param {String} firstKey The first key to duplicate
|
||||
* @param {String} secondKey The second key to duplicate
|
||||
* @param {string} app App link.
|
||||
* @returns {string} Transformed app link or the original arg if
|
||||
* no transfromation is needed.
|
||||
*/
|
||||
export function duplicateKeys(input, firstKey, secondKey) {
|
||||
// If array provided, recursively call on all elements
|
||||
if (_.isArray(input)) {
|
||||
return input.map((item) => duplicateKeys(item, firstKey, secondKey));
|
||||
function toCacheKey(app) {
|
||||
if (!isEnvOptionEnabled('APPIUM_APPS_CACHE_IGNORE_URL_QUERY') || !isSupportedUrl(app)) {
|
||||
return app;
|
||||
}
|
||||
|
||||
// If object, create duplicates for keys and then recursively call on values
|
||||
if (_.isPlainObject(input)) {
|
||||
const resultObj = {};
|
||||
for (let [key, value] of _.toPairs(input)) {
|
||||
const recursivelyCalledValue = duplicateKeys(value, firstKey, secondKey);
|
||||
if (key === firstKey) {
|
||||
resultObj[secondKey] = recursivelyCalledValue;
|
||||
} else if (key === secondKey) {
|
||||
resultObj[firstKey] = recursivelyCalledValue;
|
||||
}
|
||||
resultObj[key] = recursivelyCalledValue;
|
||||
}
|
||||
return resultObj;
|
||||
}
|
||||
|
||||
// Base case. Return primitives without doing anything.
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a desired capability and tries to JSON.parse it as an array,
|
||||
* and either returns the parsed array or a singleton array.
|
||||
*
|
||||
* @param {string|Array<String>} cap A desired capability
|
||||
*/
|
||||
export function parseCapsArray(cap) {
|
||||
if (_.isArray(cap)) {
|
||||
return cap;
|
||||
}
|
||||
|
||||
let parsedCaps;
|
||||
try {
|
||||
parsedCaps = JSON.parse(cap);
|
||||
if (_.isArray(parsedCaps)) {
|
||||
return parsedCaps;
|
||||
const {href, search} = parseAppLink(app);
|
||||
if (href && search) {
|
||||
return href.replace(search, '');
|
||||
}
|
||||
} catch (ign) {
|
||||
logger.warn(`Failed to parse capability as JSON array`);
|
||||
}
|
||||
if (_.isString(cap)) {
|
||||
return [cap];
|
||||
}
|
||||
throw new Error(`must provide a string or JSON Array; received ${cap}`);
|
||||
if (href) {
|
||||
return href;
|
||||
}
|
||||
} catch {}
|
||||
return app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a string that uniquely describes driver instance
|
||||
* Safely parses the given app link to a URL object
|
||||
*
|
||||
* @param {import('@appium/types').Core} obj driver instance
|
||||
* @param {string?} sessionId session identifier (if exists)
|
||||
* @param {string} appLink
|
||||
* @returns {URL|import('@appium/types').StringRecord} Parsed URL object
|
||||
* or an empty object if the parsing has failed
|
||||
*/
|
||||
function parseAppLink(appLink) {
|
||||
try {
|
||||
return new URL(appLink);
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether we can threat the given app link
|
||||
* as a URL,
|
||||
*
|
||||
* @param {string} app
|
||||
* @returns {boolean} True if app is a supported URL
|
||||
*/
|
||||
function isSupportedUrl(app) {
|
||||
try {
|
||||
const {protocol} = parseAppLink(app);
|
||||
return ['http:', 'https:'].includes(protocol);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given environment option is enabled
|
||||
*
|
||||
* @param {string} optionName Option name
|
||||
* @param {boolean|null} [defaultValue=null] The value to return if the given env value
|
||||
* is not set explcitly
|
||||
* @returns {boolean} True if the option is enabled
|
||||
*/
|
||||
function isEnvOptionEnabled(optionName, defaultValue = null) {
|
||||
const value = process.env[optionName];
|
||||
if (!_.isNull(defaultValue) && _.isEmpty(value)) {
|
||||
return defaultValue;
|
||||
}
|
||||
return !_.isEmpty(value) && !['0', 'false', 'no'].includes(_.toLower(value));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} [envVarName]
|
||||
* @param {number} defaultValue
|
||||
* @returns {number}
|
||||
*/
|
||||
function toNaturalNumber(defaultValue, envVarName) {
|
||||
if (!envVarName || _.isUndefined(process.env[envVarName])) {
|
||||
return defaultValue;
|
||||
}
|
||||
const num = parseInt(`${process.env[envVarName]}`, 10);
|
||||
return num > 0 ? num : defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} app
|
||||
* @param {string[]} supportedAppExtensions
|
||||
* @returns {string}
|
||||
*/
|
||||
export function generateDriverLogPrefix(obj, sessionId = null) {
|
||||
const instanceName = `${obj.constructor.name}@${node.getObjectId(obj).substring(0, 4)}`;
|
||||
return sessionId ? `${instanceName} (${sessionId.substring(0, 8)})` : instanceName;
|
||||
function verifyAppExtension(app, supportedAppExtensions) {
|
||||
if (supportedAppExtensions.map(_.toLower).includes(_.toLower(path.extname(app)))) {
|
||||
return app;
|
||||
}
|
||||
throw new Error(
|
||||
`New app path '${app}' did not have ` +
|
||||
`${util.pluralize('extension', supportedAppExtensions.length, false)}: ` +
|
||||
supportedAppExtensions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} folderPath
|
||||
* @returns {Promise<number>}
|
||||
*/
|
||||
async function calculateFolderIntegrity(folderPath) {
|
||||
return (await fs.glob('**/*', {cwd: folderPath})).length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} filePath
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
async function calculateFileIntegrity(filePath) {
|
||||
return await fs.hash(filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} currentPath
|
||||
* @param {import('@appium/types').StringRecord} expectedIntegrity
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async function isAppIntegrityOk(currentPath, expectedIntegrity = {}) {
|
||||
if (!(await fs.exists(currentPath))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Folder integrity check is simple:
|
||||
// Verify the previous amount of files is not greater than the current one.
|
||||
// We don't want to use equality comparison because of an assumption that the OS might
|
||||
// create some unwanted service files/cached inside of that folder or its subfolders.
|
||||
// Ofc, validating the hash sum of each file (or at least of file path) would be much
|
||||
// more precise, but we don't need to be very precise here and also don't want to
|
||||
// overuse RAM and have a performance drop.
|
||||
return (await fs.stat(currentPath)).isDirectory()
|
||||
? (await calculateFolderIntegrity(currentPath)) >= expectedIntegrity?.folder
|
||||
: (await calculateFileIntegrity(currentPath)) === expectedIntegrity?.file;
|
||||
}
|
||||
|
||||
/** @type {import('@appium/types').DriverHelpers} */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/base-driver",
|
||||
"version": "9.7.0",
|
||||
"version": "9.8.0",
|
||||
"description": "Base driver class for Appium drivers",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -44,8 +44,8 @@
|
||||
"test:types": "tsd"
|
||||
},
|
||||
"dependencies": {
|
||||
"@appium/support": "^4.2.6",
|
||||
"@appium/types": "^0.18.0",
|
||||
"@appium/support": "^4.3.0",
|
||||
"@appium/types": "^0.19.0",
|
||||
"@colors/colors": "1.6.0",
|
||||
"@types/async-lock": "1.4.2",
|
||||
"@types/bluebird": "3.5.42",
|
||||
@@ -67,7 +67,7 @@
|
||||
"path-to-regexp": "6.2.2",
|
||||
"serve-favicon": "2.5.0",
|
||||
"source-map-support": "0.5.21",
|
||||
"type-fest": "4.18.3",
|
||||
"type-fest": "4.19.0",
|
||||
"validate.js": "0.13.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.2.33](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.32...@appium/base-plugin@2.2.33) (2024-06-06)
|
||||
|
||||
**Note:** Version bump only for package @appium/base-plugin
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.2.32](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.31...@appium/base-plugin@2.2.32) (2024-05-27)
|
||||
|
||||
**Note:** Version bump only for package @appium/base-plugin
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/base-plugin",
|
||||
"version": "2.2.32",
|
||||
"version": "2.2.33",
|
||||
"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.7.0",
|
||||
"@appium/support": "^4.2.6"
|
||||
"@appium/base-driver": "^9.8.0",
|
||||
"@appium/support": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.1.0](https://github.com/appium/appium/compare/@appium/doctor@2.0.37...@appium/doctor@2.1.0) (2024-06-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **appium:** Replace npmlog with the local fork ([#20190](https://github.com/appium/appium/issues/20190)) ([8915934](https://github.com/appium/appium/commit/8915934270243bfb46c4d104a098ce1cc481b0ff))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **doctor:** update dependency appium-adb to v12.4.1 ([e3e1757](https://github.com/appium/appium/commit/e3e1757c564cffd467f3e9931f9aaa5a973fa825))
|
||||
* **doctor:** update dependency appium-adb to v12.4.2 ([bea47aa](https://github.com/appium/appium/commit/bea47aacca1b1a27cce48b027246513e674c2bb7))
|
||||
* **support:** update dependency teen_process to v2.1.4 ([96a7a3f](https://github.com/appium/appium/commit/96a7a3f23bead7c1d18700550138cd2d70ce5e3c))
|
||||
|
||||
|
||||
|
||||
## [2.0.37](https://github.com/appium/appium/compare/@appium/doctor@2.0.36...@appium/doctor@2.0.37) (2024-05-27)
|
||||
|
||||
|
||||
|
||||
@@ -44,28 +44,26 @@ export async function prompt(question) {
|
||||
return await inquirer.prompt(question);
|
||||
}
|
||||
|
||||
let actualLog;
|
||||
let onLogMessageHandler = null;
|
||||
|
||||
export function configureBinaryLog(opts) {
|
||||
actualLog = log.unwrap().log;
|
||||
log.unwrap().log = function (level, prefix, msg) {
|
||||
let l = this.levels[level];
|
||||
if (l < this.levels[this.level]) return; // eslint-disable-line curly
|
||||
actualLog(level, prefix, msg);
|
||||
|
||||
if (isFunction(opts.onLogMessage)) {
|
||||
opts.onLogMessage(level, prefix, msg);
|
||||
}
|
||||
const internalLogger = log.unwrap();
|
||||
if (isFunction(opts.onLogMessage) && !onLogMessageHandler) {
|
||||
onLogMessageHandler = (/** @type {import('@appium/logger').MessageObject} */ msg) => opts.onLogMessage(
|
||||
msg.level, msg.prefix, msg.message
|
||||
);
|
||||
internalLogger.on('log', onLogMessageHandler);
|
||||
};
|
||||
log.level = opts.debug ? 'debug' : 'info';
|
||||
internalLogger.level = opts.debug ? 'debug' : 'info';
|
||||
}
|
||||
|
||||
/**
|
||||
* If {@link configureBinaryLog} was called, this will restore the original `log` function.
|
||||
*/
|
||||
export function resetLog() {
|
||||
if (actualLog) {
|
||||
log.unwrap().log = actualLog;
|
||||
if (onLogMessageHandler) {
|
||||
log.unwrap().off('log', onLogMessageHandler);
|
||||
onLogMessageHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/doctor",
|
||||
"version": "2.0.37",
|
||||
"version": "2.1.0",
|
||||
"description": "Test environment for fitness to run Appium",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -44,16 +44,16 @@
|
||||
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@appium/support": "^4.2.6",
|
||||
"@appium/support": "^4.3.0",
|
||||
"@colors/colors": "1.6.0",
|
||||
"@types/bluebird": "3.5.42",
|
||||
"@types/teen_process": "2.0.4",
|
||||
"appium-adb": "12.4.0",
|
||||
"appium-adb": "12.4.2",
|
||||
"bluebird": "3.7.2",
|
||||
"inquirer": "9.2.12",
|
||||
"lodash": "4.17.21",
|
||||
"source-map-support": "0.5.21",
|
||||
"teen_process": "2.1.3",
|
||||
"teen_process": "2.1.4",
|
||||
"yargs": "17.7.2"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.0.9](https://github.com/appium/appium/compare/@appium/docutils@1.0.8...@appium/docutils@1.0.9) (2024-06-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **docutils:** update dependency yaml to v2.4.3 ([848eb00](https://github.com/appium/appium/commit/848eb00afbd1cab76a6a1c3d0f4a2a0b1acee0d0))
|
||||
* **support:** update dependency @types/which to v3 ([#20164](https://github.com/appium/appium/issues/20164)) ([57b0406](https://github.com/appium/appium/commit/57b0406a33bc687c731f9e7fedd56e1b07c3cc67))
|
||||
* **support:** update dependency teen_process to v2.1.4 ([96a7a3f](https://github.com/appium/appium/commit/96a7a3f23bead7c1d18700550138cd2d70ce5e3c))
|
||||
* **types:** update dependency type-fest to v4.19.0 ([#20193](https://github.com/appium/appium/issues/20193)) ([db62358](https://github.com/appium/appium/commit/db62358dbac25de2a75fdc7493338d98b1422c84))
|
||||
|
||||
|
||||
|
||||
## [1.0.8](https://github.com/appium/appium/compare/@appium/docutils@1.0.7...@appium/docutils@1.0.8) (2024-05-27)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/docutils",
|
||||
"version": "1.0.8",
|
||||
"version": "1.0.9",
|
||||
"description": "Documentation generation utilities for Appium and related projects",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -48,10 +48,10 @@
|
||||
"start": "node ./build/lib/cli/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@appium/support": "^4.2.6",
|
||||
"@appium/support": "^4.3.0",
|
||||
"@appium/tsconfig": "^0.3.3",
|
||||
"@sliphua/lilconfig-ts-loader": "3.2.2",
|
||||
"@types/which": "3.0.3",
|
||||
"@types/which": "3.0.4",
|
||||
"chalk": "4.1.2",
|
||||
"consola": "3.2.3",
|
||||
"diff": "5.2.0",
|
||||
@@ -62,10 +62,10 @@
|
||||
"read-pkg": "5.2.0",
|
||||
"semver": "7.6.2",
|
||||
"source-map-support": "0.5.21",
|
||||
"teen_process": "2.1.3",
|
||||
"type-fest": "4.18.3",
|
||||
"teen_process": "2.1.4",
|
||||
"type-fest": "4.19.0",
|
||||
"typescript": "5.4.5",
|
||||
"yaml": "2.4.2",
|
||||
"yaml": "2.4.3",
|
||||
"yargs": "17.7.2",
|
||||
"yargs-parser": "21.1.1"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
mkdocs==1.6.0
|
||||
mkdocs-git-revision-date-localized-plugin==1.2.5
|
||||
mkdocs-git-revision-date-localized-plugin==1.2.6
|
||||
mkdocs-material==9.5.25
|
||||
mkdocs-redirects==1.2.1
|
||||
mike==2.1.1
|
||||
|
||||
@@ -3,6 +3,15 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.4.25](https://github.com/appium/appium/compare/@appium/driver-test-support@0.4.24...@appium/driver-test-support@0.4.25) (2024-06-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **types:** update dependency type-fest to v4.19.0 ([#20193](https://github.com/appium/appium/issues/20193)) ([db62358](https://github.com/appium/appium/commit/db62358dbac25de2a75fdc7493338d98b1422c84))
|
||||
|
||||
|
||||
|
||||
## [0.4.24](https://github.com/appium/appium/compare/@appium/driver-test-support@0.4.23...@appium/driver-test-support@0.4.24) (2024-05-27)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/driver-test-support",
|
||||
"version": "0.4.24",
|
||||
"version": "0.4.25",
|
||||
"description": "Test utilities for Appium drivers",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -41,7 +41,7 @@
|
||||
},
|
||||
"types": "./build/lib/index.d.ts",
|
||||
"dependencies": {
|
||||
"@appium/types": "^0.18.0",
|
||||
"@appium/types": "^0.19.0",
|
||||
"@types/lodash": "4.17.4",
|
||||
"@types/stoppable": "1.1.3",
|
||||
"axios": "1.7.2",
|
||||
@@ -52,7 +52,7 @@
|
||||
"sinon": "18.0.0",
|
||||
"source-map-support": "0.5.21",
|
||||
"stoppable": "1.1.0",
|
||||
"type-fest": "4.18.3"
|
||||
"type-fest": "4.19.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"appium": "^2.0.0-beta.43",
|
||||
|
||||
@@ -3,6 +3,15 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [3.0.30](https://github.com/appium/appium/compare/@appium/execute-driver-plugin@3.0.29...@appium/execute-driver-plugin@3.0.30) (2024-06-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **execute-driver-plugin:** update dependency webdriverio to v8.38.2 ([c8f9979](https://github.com/appium/appium/commit/c8f997973cc21673f95d02c92d43a2981b8713b8))
|
||||
|
||||
|
||||
|
||||
## [3.0.29](https://github.com/appium/appium/compare/@appium/execute-driver-plugin@3.0.28...@appium/execute-driver-plugin@3.0.29) (2024-05-27)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/execute-driver-plugin",
|
||||
"version": "3.0.29",
|
||||
"version": "3.0.30",
|
||||
"description": "Plugin for batching and executing driver commands with Appiums",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -43,7 +43,7 @@
|
||||
"lodash": "4.17.21",
|
||||
"source-map-support": "0.5.21",
|
||||
"vm2": "3.9.19",
|
||||
"webdriverio": "8.38.0"
|
||||
"webdriverio": "8.38.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"appium": "^2.0.0-beta.35"
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [3.1.37](https://github.com/appium/appium/compare/@appium/fake-plugin@3.1.36...@appium/fake-plugin@3.1.37) (2024-06-06)
|
||||
|
||||
**Note:** Version bump only for package @appium/fake-plugin
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [3.1.36](https://github.com/appium/appium/compare/@appium/fake-plugin@3.1.35...@appium/fake-plugin@3.1.36) (2024-05-27)
|
||||
|
||||
**Note:** Version bump only for package @appium/fake-plugin
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/fake-plugin",
|
||||
"version": "3.1.36",
|
||||
"version": "3.1.37",
|
||||
"description": "A fake Appium 2.0 plugin",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -39,8 +39,8 @@
|
||||
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@appium/base-plugin": "^2.2.32",
|
||||
"@appium/support": "^4.2.6",
|
||||
"@appium/base-plugin": "^2.2.33",
|
||||
"@appium/support": "^4.3.0",
|
||||
"@types/bluebird": "3.5.42",
|
||||
"bluebird": "3.7.2",
|
||||
"lodash": "4.17.21",
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [3.0.8](https://github.com/appium/appium/compare/@appium/images-plugin@3.0.7...@appium/images-plugin@3.0.8) (2024-06-06)
|
||||
|
||||
**Note:** Version bump only for package @appium/images-plugin
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [3.0.7](https://github.com/appium/appium/compare/@appium/images-plugin@3.0.6...@appium/images-plugin@3.0.7) (2024-05-27)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/images-plugin",
|
||||
"version": "3.0.7",
|
||||
"version": "3.0.8",
|
||||
"description": "Plugin for working with images and image elements in Appium",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -40,7 +40,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@appium/opencv": "^3.0.4",
|
||||
"@appium/support": "^4.2.6",
|
||||
"@appium/support": "^4.3.0",
|
||||
"lodash": "4.17.21",
|
||||
"lru-cache": "10.2.2",
|
||||
"sharp": "0.33.4",
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## 1.1.0 (2024-06-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **appium:** Replace npmlog with the local fork ([#20190](https://github.com/appium/appium/issues/20190)) ([8915934](https://github.com/appium/appium/commit/8915934270243bfb46c4d104a098ce1cc481b0ff))
|
||||
* **logger:** add packages/logger package from npmlog ([#20161](https://github.com/appium/appium/issues/20161)) ([70449cd](https://github.com/appium/appium/commit/70449cd077d7efc3dbc8aa498ee2072cc2dc0f22))
|
||||
@@ -0,0 +1,18 @@
|
||||
ISC License
|
||||
|
||||
Copyright npm, Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this
|
||||
software for any purpose with or without fee is hereby
|
||||
granted, provided that the above copyright notice and this
|
||||
permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND NPM DISCLAIMS ALL
|
||||
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
EVENT SHALL NPM BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
|
||||
USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
@@ -0,0 +1,31 @@
|
||||
# @appium/logger
|
||||
|
||||
> Appium's logging functionality
|
||||
|
||||
## Installation
|
||||
|
||||
```console
|
||||
npm install @appium/logger --save
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```js
|
||||
import log from '@appium/logger';
|
||||
|
||||
// additional stuff ---------------------------+
|
||||
// message ----------+ |
|
||||
// prefix ----+ | |
|
||||
// level -+ | | |
|
||||
// v v v v
|
||||
log.info('fyi', 'I have a kitty cat: %j', myKittyCat);
|
||||
```
|
||||
|
||||
## History
|
||||
|
||||
This module is forked from [npmlog](https://github.com/npm/npmlog) under ISC License because the original project has been archived.
|
||||
Please check [the npmlog changelog](https://github.com/npm/npmlog/blob/main/CHANGELOG.md) to see the list of former module updates before it was forked.
|
||||
|
||||
## License
|
||||
|
||||
ISC License
|
||||
@@ -0,0 +1,5 @@
|
||||
import log from './lib/log';
|
||||
export type * from './lib/types';
|
||||
|
||||
export {log};
|
||||
export default log;
|
||||
@@ -0,0 +1,313 @@
|
||||
import {EventEmitter} from 'node:events';
|
||||
// @ts-ignore This module does not provide type definitons
|
||||
import setBlocking from 'set-blocking';
|
||||
// @ts-ignore This module does not provide type definitons
|
||||
import consoleControl from 'console-control-strings';
|
||||
import * as util from 'node:util';
|
||||
import type {MessageObject, StyleObject, Logger, LogLevel} from './types';
|
||||
import type {Writable} from 'node:stream';
|
||||
|
||||
const DEFAULT_LOG_LEVELS: any[][] = [
|
||||
['silly', -Infinity, {inverse: true}, 'sill'],
|
||||
['verbose', 1000, {fg: 'cyan', bg: 'black'}, 'verb'],
|
||||
['info', 2000, {fg: 'green'}],
|
||||
['timing', 2500, {fg: 'green', bg: 'black'}],
|
||||
['http', 3000, {fg: 'green', bg: 'black'}],
|
||||
['notice', 3500, {fg: 'cyan', bg: 'black'}],
|
||||
['warn', 4000, {fg: 'black', bg: 'yellow'}, 'WARN'],
|
||||
['error', 5000, {fg: 'red', bg: 'black'}, 'ERR!'],
|
||||
['silent', Infinity],
|
||||
] as const;
|
||||
|
||||
setBlocking(true);
|
||||
|
||||
export class Log extends EventEmitter implements Logger {
|
||||
level: LogLevel | string;
|
||||
record: MessageObject[];
|
||||
maxRecordSize: number;
|
||||
prefixStyle: StyleObject;
|
||||
headingStyle: StyleObject;
|
||||
heading: string;
|
||||
stream: Writable; // Defaults to process.stderr
|
||||
|
||||
_colorEnabled?: boolean;
|
||||
_buffer: MessageObject[];
|
||||
_style: Record<LogLevel | string, StyleObject | undefined>;
|
||||
_levels: Record<LogLevel | string, number>;
|
||||
_disp: Record<LogLevel | string, number | string>;
|
||||
_id: number;
|
||||
_paused: boolean;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.level = 'info';
|
||||
this._buffer = [];
|
||||
this.record = [];
|
||||
this.maxRecordSize = 10000;
|
||||
this.stream = process.stderr;
|
||||
this.heading = '';
|
||||
this.prefixStyle = {fg: 'magenta'};
|
||||
this.headingStyle = {fg: 'white', bg: 'black'};
|
||||
this._id = 0;
|
||||
this._paused = false;
|
||||
|
||||
this._style = {};
|
||||
this._levels = {};
|
||||
this._disp = {};
|
||||
this.initDefaultLevels();
|
||||
|
||||
// allow 'error' prefix
|
||||
this.on('error', () => {});
|
||||
}
|
||||
|
||||
private useColor(): boolean {
|
||||
// by default, decide based on tty-ness.
|
||||
return (
|
||||
this._colorEnabled ?? Boolean(this.stream && 'isTTY' in this.stream && this.stream.isTTY)
|
||||
);
|
||||
}
|
||||
|
||||
enableColor(): void {
|
||||
this._colorEnabled = true;
|
||||
}
|
||||
|
||||
disableColor(): void {
|
||||
this._colorEnabled = false;
|
||||
}
|
||||
|
||||
// this functionality has been deliberately disabled
|
||||
enableUnicode(): void {}
|
||||
disableUnicode(): void {}
|
||||
enableProgress(): void {}
|
||||
disableProgress(): void {}
|
||||
progressEnabled(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily stop emitting, but don't drop
|
||||
*/
|
||||
pause(): void {
|
||||
this._paused = true;
|
||||
}
|
||||
|
||||
resume(): void {
|
||||
if (!this._paused) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._paused = false;
|
||||
|
||||
const b = this._buffer;
|
||||
this._buffer = [];
|
||||
for (const m of b) {
|
||||
this.emitLog(m);
|
||||
}
|
||||
}
|
||||
|
||||
silly(prefix: string, message: any, ...args: any[]): void {
|
||||
this.log('silly', prefix, message, ...args);
|
||||
}
|
||||
|
||||
verbose(prefix: string, message: any, ...args: any[]): void {
|
||||
this.log('verbose', prefix, message, ...args);
|
||||
}
|
||||
|
||||
info(prefix: string, message: any, ...args: any[]): void {
|
||||
this.log('info', prefix, message, ...args);
|
||||
}
|
||||
|
||||
timing(prefix: string, message: any, ...args: any[]): void {
|
||||
this.log('timing', prefix, message, ...args);
|
||||
}
|
||||
|
||||
http(prefix: string, message: any, ...args: any[]): void {
|
||||
this.log('http', prefix, message, ...args);
|
||||
}
|
||||
|
||||
notice(prefix: string, message: any, ...args: any[]): void {
|
||||
this.log('notice', prefix, message, ...args);
|
||||
}
|
||||
|
||||
warn(prefix: string, message: any, ...args: any[]): void {
|
||||
this.log('warn', prefix, message, ...args);
|
||||
}
|
||||
|
||||
error(prefix: string, message: any, ...args: any[]): void {
|
||||
this.log('error', prefix, message, ...args);
|
||||
}
|
||||
|
||||
silent(prefix: string, message: any, ...args: any[]): void {
|
||||
this.log('silent', prefix, message, ...args);
|
||||
}
|
||||
|
||||
addLevel(level: string, n: number, style?: StyleObject, disp?: string): void {
|
||||
this._levels[level] = n;
|
||||
this._style[level] = style;
|
||||
if (!(this as any)[level]) {
|
||||
(this as any)[level] = (prefix: string, message: any, ...args: any[]) => {
|
||||
this.log(level, prefix, message, ...args);
|
||||
};
|
||||
}
|
||||
// If 'disp' is null or undefined, use the level as a default
|
||||
this._disp[level] = disp ?? level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a log message
|
||||
* @param level
|
||||
* @param prefix
|
||||
* @param message message of the log which will be formatted using utils.format()
|
||||
* @param args additional arguments appended to the log message also formatted using utils.format()
|
||||
*/
|
||||
log(level: LogLevel | string, prefix: string, message: any, ...args: any[]): void {
|
||||
const l = this._levels[level];
|
||||
if (l === undefined) {
|
||||
this.emit('error', new Error(util.format('Undefined log level: %j', level)));
|
||||
return;
|
||||
}
|
||||
|
||||
const messageArguments: any[] = [];
|
||||
let stack: string | null = null;
|
||||
for (const formatArg of [message, ...args]) {
|
||||
messageArguments.push(formatArg);
|
||||
// resolve stack traces to a plain string.
|
||||
if (typeof formatArg === 'object' && formatArg instanceof Error && formatArg.stack) {
|
||||
Object.defineProperty(formatArg, 'stack', {
|
||||
value: (stack = formatArg.stack + ''),
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (stack) {
|
||||
messageArguments.unshift(`${stack}\n`);
|
||||
}
|
||||
const formattedMessage: string = util.format(...messageArguments);
|
||||
|
||||
const m: MessageObject = {
|
||||
id: this._id++,
|
||||
timestamp: Date.now(),
|
||||
level,
|
||||
prefix: String(prefix || ''),
|
||||
message: formattedMessage,
|
||||
};
|
||||
|
||||
this.emit('log', m);
|
||||
this.emit('log.' + level, m);
|
||||
if (m.prefix) {
|
||||
this.emit(m.prefix, m);
|
||||
}
|
||||
|
||||
this.record.push(m);
|
||||
const mrs = this.maxRecordSize;
|
||||
if (this.record.length > mrs) {
|
||||
this.record.shift();
|
||||
}
|
||||
|
||||
this.emitLog(m);
|
||||
}
|
||||
|
||||
private emitLog(m: MessageObject): void {
|
||||
if (this._paused) {
|
||||
this._buffer.push(m);
|
||||
return;
|
||||
}
|
||||
|
||||
const l = this._levels[m.level];
|
||||
if (l === undefined) {
|
||||
return;
|
||||
}
|
||||
if (l < this._levels[this.level]) {
|
||||
return;
|
||||
}
|
||||
if (l > 0 && !isFinite(l)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If 'disp' is null or undefined, use the lvl as a default
|
||||
// Allows: '', 0 as valid disp
|
||||
const disp = this._disp[m.level];
|
||||
this.clearProgress();
|
||||
for (const line of m.message.split(/\r?\n/)) {
|
||||
const heading = this.heading;
|
||||
if (heading) {
|
||||
this.write(heading, this.headingStyle);
|
||||
this.write(' ');
|
||||
}
|
||||
this.write(String(disp), this._style[m.level]);
|
||||
const p = m.prefix || '';
|
||||
if (p) {
|
||||
this.write(' ');
|
||||
}
|
||||
|
||||
this.write(p, this.prefixStyle);
|
||||
this.write(` ${line}\n`);
|
||||
}
|
||||
this.showProgress();
|
||||
}
|
||||
|
||||
private _format(msg: string, style: StyleObject = {}): string | undefined {
|
||||
if (!this.stream) {
|
||||
return;
|
||||
}
|
||||
|
||||
let output = '';
|
||||
if (this.useColor()) {
|
||||
const settings: string[] = [];
|
||||
if (style.fg) {
|
||||
settings.push(style.fg);
|
||||
}
|
||||
if (style.bg) {
|
||||
settings.push('bg' + style.bg[0].toUpperCase() + style.bg.slice(1));
|
||||
}
|
||||
if (style.bold) {
|
||||
settings.push('bold');
|
||||
}
|
||||
if (style.underline) {
|
||||
settings.push('underline');
|
||||
}
|
||||
if (style.inverse) {
|
||||
settings.push('inverse');
|
||||
}
|
||||
if (settings.length) {
|
||||
output += consoleControl.color(settings);
|
||||
}
|
||||
if (style.bell) {
|
||||
output += consoleControl.beep();
|
||||
}
|
||||
}
|
||||
output += msg;
|
||||
if (this.useColor()) {
|
||||
output += consoleControl.color('reset');
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
private write(msg: string, style: StyleObject = {}): void {
|
||||
if (!this.stream) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formatted = this._format(msg, style);
|
||||
if (formatted !== undefined) {
|
||||
this.stream.write(formatted);
|
||||
}
|
||||
}
|
||||
|
||||
private initDefaultLevels(): void {
|
||||
for (const [level, index, style, disp] of DEFAULT_LOG_LEVELS) {
|
||||
this._levels[level] = index;
|
||||
this._style[level] = style;
|
||||
this._disp[level] = disp ?? level;
|
||||
}
|
||||
}
|
||||
|
||||
// this functionality has been deliberately disabled
|
||||
private clearProgress(): void {}
|
||||
private showProgress(): void {}
|
||||
}
|
||||
|
||||
export const GLOBAL_LOG = new Log();
|
||||
export default GLOBAL_LOG;
|
||||
@@ -0,0 +1,83 @@
|
||||
import type {EventEmitter} from 'node:events';
|
||||
|
||||
export interface Logger extends EventEmitter {
|
||||
level: string;
|
||||
record: MessageObject[];
|
||||
maxRecordSize: number;
|
||||
prefixStyle: StyleObject;
|
||||
headingStyle: StyleObject;
|
||||
heading: string;
|
||||
stream: any; // Defaults to process.stderr
|
||||
|
||||
/**
|
||||
* Creates a log message
|
||||
* @param level
|
||||
* @param prefix
|
||||
* @param message message of the log which will be formatted using utils.format()
|
||||
* @param args additional arguments appended to the log message also formatted using utils.format()
|
||||
*/
|
||||
log(level: LogLevel | string, prefix: string, message: any, ...args: any[]): void;
|
||||
|
||||
/**
|
||||
* @param prefix
|
||||
* @param message message of the log which will be formatted using utils.format()
|
||||
* @param args additional arguments appended to the log message also formatted using utils.format()
|
||||
*/
|
||||
silly(prefix: string, message: any, ...args: any[]): void;
|
||||
verbose(prefix: string, message: any, ...args: any[]): void;
|
||||
info(prefix: string, message: any, ...args: any[]): void;
|
||||
timing(prefix: string, message: any, ...args: any[]): void;
|
||||
http(prefix: string, message: any, ...args: any[]): void;
|
||||
notice(prefix: string, message: any, ...args: any[]): void;
|
||||
warn(prefix: string, message: any, ...args: any[]): void;
|
||||
error(prefix: string, message: any, ...args: any[]): void;
|
||||
silent(prefix: string, message: any, ...args: any[]): void;
|
||||
|
||||
enableColor(): void;
|
||||
disableColor(): void;
|
||||
|
||||
enableProgress(): void;
|
||||
disableProgress(): void;
|
||||
progressEnabled(): boolean;
|
||||
|
||||
enableUnicode(): void;
|
||||
disableUnicode(): void;
|
||||
|
||||
pause(): void;
|
||||
resume(): void;
|
||||
|
||||
addLevel(level: string, n: number, style?: StyleObject, disp?: string): void;
|
||||
|
||||
// Allows for custom log levels
|
||||
// log.addLevel("custom", level)
|
||||
// log.custom(prefix, message)
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export type LogLevel =
|
||||
| 'silly'
|
||||
| 'verbose'
|
||||
| 'info'
|
||||
| 'timing'
|
||||
| 'http'
|
||||
| 'notice'
|
||||
| 'warn'
|
||||
| 'error'
|
||||
| 'silent';
|
||||
|
||||
export interface StyleObject {
|
||||
fg?: string | undefined;
|
||||
bg?: string | undefined;
|
||||
bold?: boolean | undefined;
|
||||
inverse?: boolean | undefined;
|
||||
underline?: boolean | undefined;
|
||||
bell?: boolean | undefined;
|
||||
}
|
||||
|
||||
export interface MessageObject {
|
||||
id: number;
|
||||
timestamp: number;
|
||||
level: string;
|
||||
prefix: string;
|
||||
message: string;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "@appium/logger",
|
||||
"version": "1.1.0",
|
||||
"author": "https://github.com/appium",
|
||||
"description": "A Universal Logger For The Appium Ecosystem",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appium/appium.git",
|
||||
"directory": "packages/logger"
|
||||
},
|
||||
"main": "build/index.js",
|
||||
"types": "index.ts",
|
||||
"files": [
|
||||
"index.ts",
|
||||
"lib",
|
||||
"build",
|
||||
"tsconfig.json",
|
||||
"!build/tsconfig.tsbuildinfo",
|
||||
"CHANGELOG.md"
|
||||
],
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "npm run test:unit",
|
||||
"test:smoke": "node ./build/index.js",
|
||||
"test:unit": "mocha --exit --timeout 1m \"./test/unit/**/*-specs.js\""
|
||||
},
|
||||
"dependencies": {
|
||||
"console-control-strings": "1.1.0",
|
||||
"set-blocking": "2.0.0"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
|
||||
"npm": ">=8"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/appium/appium/issues"
|
||||
},
|
||||
"homepage": "https://appium.io",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "8480a85ce2fa466360e0fb1a7f66628331907f02",
|
||||
"keywords": [
|
||||
"automation",
|
||||
"javascript",
|
||||
"selenium",
|
||||
"webdriver",
|
||||
"ios",
|
||||
"android",
|
||||
"firefoxos",
|
||||
"testing"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,425 @@
|
||||
/* eslint-disable no-console */
|
||||
import { Log } from '../../lib/log';
|
||||
import {Stream} from 'node:stream';
|
||||
|
||||
describe('basic', async function () {
|
||||
const chai = await import('chai');
|
||||
chai.should();
|
||||
|
||||
let log;
|
||||
|
||||
describe('logging', function () {
|
||||
let s;
|
||||
let result = [];
|
||||
let logEvents = [];
|
||||
let logInfoEvents = [];
|
||||
let logPrefixEvents = [];
|
||||
const resultExpect = [
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[7msill\u001b[0m \u001b[0m\u001b[35msilly prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[36;40mverb\u001b[0m \u001b[0m\u001b[35mverbose prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[32minfo\u001b[0m \u001b[0m\u001b[35minfo prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[32;40mtiming\u001b[0m \u001b[0m\u001b[35mtiming prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[32;40mhttp\u001b[0m \u001b[0m\u001b[35mhttp prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[36;40mnotice\u001b[0m \u001b[0m\u001b[35mnotice prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[30;43mWARN\u001b[0m \u001b[0m\u001b[35mwarn prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[31;40mERR!\u001b[0m \u001b[0m\u001b[35merror prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[32minfo\u001b[0m \u001b[0m\u001b[35minfo prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[32;40mtiming\u001b[0m \u001b[0m\u001b[35mtiming prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[32;40mhttp\u001b[0m \u001b[0m\u001b[35mhttp prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[36;40mnotice\u001b[0m \u001b[0m\u001b[35mnotice prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[30;43mWARN\u001b[0m \u001b[0m\u001b[35mwarn prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[31;40mERR!\u001b[0m \u001b[0m\u001b[35merror prefix\u001b[0m x = {"foo":{"bar":"baz"}}\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[31;40mERR!\u001b[0m \u001b[0m\u001b[35m404\u001b[0m This is a longer\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[31;40mERR!\u001b[0m \u001b[0m\u001b[35m404\u001b[0m message, with some details\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[31;40mERR!\u001b[0m \u001b[0m\u001b[35m404\u001b[0m and maybe a stack.\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u001b[31;40mERR!\u001b[0m \u001b[0m\u001b[35m404\u001b[0m \n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u0007noise\u001b[0m\u001b[35m\u001b[0m LOUD NOISES\n',
|
||||
// eslint-disable-next-line max-len
|
||||
'\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m\u0007noise\u001b[0m \u001b[0m\u001b[35merror\u001b[0m erroring\n',
|
||||
'\u001b[0m',
|
||||
];
|
||||
const logPrefixEventsExpect = [
|
||||
{ id: 2,
|
||||
level: 'info',
|
||||
prefix: 'info prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 11,
|
||||
level: 'info',
|
||||
prefix: 'info prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 20,
|
||||
level: 'info',
|
||||
prefix: 'info prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
];
|
||||
// should be the same.
|
||||
const logInfoEventsExpect = logPrefixEventsExpect;
|
||||
const logEventsExpect = [
|
||||
{ id: 0,
|
||||
level: 'silly',
|
||||
prefix: 'silly prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 1,
|
||||
level: 'verbose',
|
||||
prefix: 'verbose prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 2,
|
||||
level: 'info',
|
||||
prefix: 'info prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 3,
|
||||
level: 'timing',
|
||||
prefix: 'timing prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 4,
|
||||
level: 'http',
|
||||
prefix: 'http prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 5,
|
||||
level: 'notice',
|
||||
prefix: 'notice prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 6,
|
||||
level: 'warn',
|
||||
prefix: 'warn prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 7,
|
||||
level: 'error',
|
||||
prefix: 'error prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 8,
|
||||
level: 'silent',
|
||||
prefix: 'silent prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 9,
|
||||
level: 'silly',
|
||||
prefix: 'silly prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 10,
|
||||
level: 'verbose',
|
||||
prefix: 'verbose prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 11,
|
||||
level: 'info',
|
||||
prefix: 'info prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 12,
|
||||
level: 'timing',
|
||||
prefix: 'timing prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 13,
|
||||
level: 'http',
|
||||
prefix: 'http prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 14,
|
||||
level: 'notice',
|
||||
prefix: 'notice prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 15,
|
||||
level: 'warn',
|
||||
prefix: 'warn prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 16,
|
||||
level: 'error',
|
||||
prefix: 'error prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 17,
|
||||
level: 'silent',
|
||||
prefix: 'silent prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 18,
|
||||
level: 'silly',
|
||||
prefix: 'silly prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 19,
|
||||
level: 'verbose',
|
||||
prefix: 'verbose prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 20,
|
||||
level: 'info',
|
||||
prefix: 'info prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 21,
|
||||
level: 'timing',
|
||||
prefix: 'timing prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 22,
|
||||
level: 'http',
|
||||
prefix: 'http prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 23,
|
||||
level: 'notice',
|
||||
prefix: 'notice prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 24,
|
||||
level: 'warn',
|
||||
prefix: 'warn prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 25,
|
||||
level: 'error',
|
||||
prefix: 'error prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 26,
|
||||
level: 'silent',
|
||||
prefix: 'silent prefix',
|
||||
message: 'x = {"foo":{"bar":"baz"}}',
|
||||
},
|
||||
{ id: 27,
|
||||
level: 'error',
|
||||
prefix: '404',
|
||||
message: 'This is a longer\nmessage, with some details\nand maybe a stack.\n',
|
||||
},
|
||||
{ id: 28,
|
||||
level: 'noise',
|
||||
prefix: '',
|
||||
message: 'LOUD NOISES',
|
||||
},
|
||||
{ id: 29,
|
||||
level: 'noise',
|
||||
prefix: 'error',
|
||||
message: 'erroring',
|
||||
},
|
||||
];
|
||||
|
||||
this.beforeEach(function () {
|
||||
result = [];
|
||||
logEvents = [];
|
||||
logInfoEvents = [];
|
||||
logPrefixEvents = [];
|
||||
|
||||
log = new Log();
|
||||
s = new Stream();
|
||||
s.write = (m) => result.push(m);
|
||||
s.writable = true;
|
||||
s.isTTY = true;
|
||||
s.end = () => {};
|
||||
log.stream = s;
|
||||
log.heading = 'npm';
|
||||
});
|
||||
|
||||
it('should work', function () {
|
||||
log.stream.should.equal(s);
|
||||
log.on('log', logEvents.push.bind(logEvents));
|
||||
log.on('log.info', logInfoEvents.push.bind(logInfoEvents));
|
||||
log.on('info prefix', logPrefixEvents.push.bind(logPrefixEvents));
|
||||
|
||||
console.error('log.level=silly');
|
||||
log.level = 'silly';
|
||||
log.silly('silly prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.verbose('verbose prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.info('info prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.timing('timing prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.http('http prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.notice('notice prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.warn('warn prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.error('error prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.silent('silent prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
|
||||
console.error('log.level=silent');
|
||||
log.level = 'silent';
|
||||
log.silly('silly prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.verbose('verbose prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.info('info prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.timing('timing prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.http('http prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.notice('notice prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.warn('warn prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.error('error prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.silent('silent prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
|
||||
console.error('log.level=info');
|
||||
log.level = 'info';
|
||||
log.silly('silly prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.verbose('verbose prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.info('info prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.timing('timing prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.http('http prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.notice('notice prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.warn('warn prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.error('error prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.silent('silent prefix', 'x = %j', { foo: { bar: 'baz' } });
|
||||
log.error('404', 'This is a longer\n' +
|
||||
'message, with some details\n' +
|
||||
'and maybe a stack.\n');
|
||||
log.addLevel('noise', 10000, { bell: true });
|
||||
log.noise(false, 'LOUD NOISES');
|
||||
log.noise('error', 'erroring');
|
||||
|
||||
result.join('').trim().should.equal(resultExpect.join('').trim());
|
||||
const withoutTimestamps = (x) => x.map((m) => {
|
||||
Boolean(m.timestamp).should.be.true;
|
||||
const copy = JSON.parse(JSON.stringify(m));
|
||||
delete copy.timestamp;
|
||||
return copy;
|
||||
});
|
||||
withoutTimestamps(log.record).should.eql(logEventsExpect);
|
||||
withoutTimestamps(logEvents).should.eql(logEventsExpect);
|
||||
withoutTimestamps(logInfoEvents).should.eql(logInfoEventsExpect);
|
||||
withoutTimestamps(logPrefixEvents).should.eql(logPrefixEventsExpect);
|
||||
});
|
||||
});
|
||||
|
||||
describe('utils', function () {
|
||||
it('enableColor', function () {
|
||||
log.enableColor();
|
||||
log.useColor().should.be.true;
|
||||
});
|
||||
|
||||
it('disableColor', function () {
|
||||
log.disableColor();
|
||||
log.useColor().should.be.false;
|
||||
});
|
||||
|
||||
it('_buffer while paused', function () {
|
||||
log.pause();
|
||||
log.log('verbose', 'test', 'test log');
|
||||
log._buffer.length.should.equal(1);
|
||||
log.resume();
|
||||
log._buffer.length.should.equal(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('log.log', function () {
|
||||
beforeEach(function () {
|
||||
log = new Log();
|
||||
});
|
||||
|
||||
it('emits error on bad loglevel', async function() {
|
||||
await new Promise((resolve, reject) => {
|
||||
log.once('error', (err) => {
|
||||
/Undefined log level: "asdf"/.test(err).should.be.true;
|
||||
resolve();
|
||||
});
|
||||
log.log('asdf', 'bad loglevel');
|
||||
setTimeout(reject, 1000);
|
||||
});
|
||||
});
|
||||
|
||||
it('resolves stack traces to a plain string', async function() {
|
||||
await new Promise((resolve, reject) => {
|
||||
log.once('log', (m) => {
|
||||
/Error: with a stack trace/.test(m.message).should.be.true;
|
||||
/at Test/.test(m.message).should.be.true;
|
||||
resolve();
|
||||
});
|
||||
const err = new Error('with a stack trace');
|
||||
log.log('verbose', 'oops', err);
|
||||
setTimeout(reject, 1000);
|
||||
});
|
||||
});
|
||||
|
||||
it('max record size', function() {
|
||||
log.maxRecordSize = 3;
|
||||
log.log('verbose', 'test', 'log 1');
|
||||
log.log('verbose', 'test', 'log 2');
|
||||
log.log('verbose', 'test', 'log 3');
|
||||
log.log('verbose', 'test', 'log 4');
|
||||
log.record.length.should.equal(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('stream', function () {
|
||||
beforeEach(function () {
|
||||
log = new Log();
|
||||
});
|
||||
|
||||
it('write with no stream', function() {
|
||||
log.stream = null;
|
||||
log.write('message');
|
||||
});
|
||||
});
|
||||
|
||||
describe('emitLog', function () {
|
||||
beforeEach(function () {
|
||||
log = new Log();
|
||||
});
|
||||
|
||||
it('to nonexistant level', function() {
|
||||
log.emitLog({ prefix: 'test', level: 'asdf' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('format', function () {
|
||||
beforeEach(function () {
|
||||
log = new Log();
|
||||
});
|
||||
|
||||
it('with nonexistant stream', function() {
|
||||
log.stream = null;
|
||||
(log._format('message') === undefined).should.be.true;
|
||||
});
|
||||
it('fg', function () {
|
||||
log.enableColor();
|
||||
const o = log._format('test message', { bg: 'blue' });
|
||||
o.includes('\u001b[44mtest message\u001b[0m').should.be.true;
|
||||
});
|
||||
it('bg', function () {
|
||||
log.enableColor();
|
||||
const o = log._format('test message', { bg: 'white' });
|
||||
o.includes('\u001b[47mtest message\u001b[0m').should.be.true;
|
||||
});
|
||||
it('bold', function () {
|
||||
log.enableColor();
|
||||
const o = log._format('test message', { bold: true });
|
||||
o.includes('\u001b[1mtest message\u001b[0m').should.be.true;
|
||||
});
|
||||
it('underline', function () {
|
||||
log.enableColor();
|
||||
const o = log._format('test message', { underline: true });
|
||||
o.includes('\u001b[4mtest message\u001b[0m').should.be.true;
|
||||
});
|
||||
it('inverse', function () {
|
||||
log.enableColor();
|
||||
const o = log._format('test message', { inverse: true });
|
||||
o.includes('\u001b[7mtest message\u001b[0m').should.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Log } from '../../lib/log';
|
||||
import { waitForCondition } from 'asyncbox';
|
||||
|
||||
describe('display', function () {
|
||||
let log;
|
||||
|
||||
describe('explicitly set new log level display to empty string', function () {
|
||||
let actual;
|
||||
|
||||
beforeEach(function () {
|
||||
actual = '';
|
||||
log = new Log();
|
||||
log.write = (msg) => {
|
||||
actual += msg;
|
||||
};
|
||||
});
|
||||
|
||||
it('explicitly set new log level display to empty string', async function () {
|
||||
log.addLevel('explicitNoLevelDisplayed', 20000, {}, '');
|
||||
log.explicitNoLevelDisplayed('1', '2');
|
||||
await waitForCondition(() => actual.trim() === '1 2', {waitMs: 1000, intervalMs: 50});
|
||||
|
||||
actual = '';
|
||||
log.explicitNoLevelDisplayed('', '1');
|
||||
await waitForCondition(() => actual.trim() === '1', {waitMs: 1000, intervalMs: 50});
|
||||
});
|
||||
|
||||
it('explicitly set new log level display to 0', async function () {
|
||||
log.addLevel('explicitNoLevelDisplayed', 20000, {}, 0);
|
||||
log.explicitNoLevelDisplayed('', '1');
|
||||
await waitForCondition(() => actual.trim() === '0 1', {waitMs: 1000, intervalMs: 50});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "@appium/tsconfig/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"strict": false,
|
||||
"outDir": "build",
|
||||
"types": ["node"],
|
||||
"checkJs": true
|
||||
},
|
||||
"include": [
|
||||
"index.ts",
|
||||
"lib"
|
||||
]
|
||||
}
|
||||
@@ -3,6 +3,15 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.3.32](https://github.com/appium/appium/compare/@appium/plugin-test-support@0.3.31...@appium/plugin-test-support@0.3.32) (2024-06-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **support:** update dependency teen_process to v2.1.4 ([96a7a3f](https://github.com/appium/appium/commit/96a7a3f23bead7c1d18700550138cd2d70ce5e3c))
|
||||
|
||||
|
||||
|
||||
## [0.3.31](https://github.com/appium/appium/compare/@appium/plugin-test-support@0.3.30...@appium/plugin-test-support@0.3.31) (2024-05-27)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/plugin-test-support",
|
||||
"version": "0.3.31",
|
||||
"version": "0.3.32",
|
||||
"description": "Testing utilities for Appium plugins",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -41,11 +41,11 @@
|
||||
"test:unit": "exit 0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@appium/types": "^0.18.0",
|
||||
"@appium/types": "^0.19.0",
|
||||
"get-port": "5.1.1",
|
||||
"log-symbols": "4.1.0",
|
||||
"source-map-support": "0.5.21",
|
||||
"teen_process": "2.1.3"
|
||||
"teen_process": "2.1.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"appium": "^2.0.0-beta.43",
|
||||
|
||||
@@ -3,6 +3,23 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [4.3.0](https://github.com/appium/appium/compare/@appium/support@4.2.6...@appium/support@4.3.0) (2024-06-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **appium:** Replace npmlog with the local fork ([#20190](https://github.com/appium/appium/issues/20190)) ([8915934](https://github.com/appium/appium/commit/8915934270243bfb46c4d104a098ce1cc481b0ff))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **support:** Make sure response stream is defined while stopping it ([#20189](https://github.com/appium/appium/issues/20189)) ([4fd6893](https://github.com/appium/appium/commit/4fd68931465dd2ed3490bcebad7ccff3dacc9b3a))
|
||||
* **support:** update dependency @types/which to v3 ([#20164](https://github.com/appium/appium/issues/20164)) ([57b0406](https://github.com/appium/appium/commit/57b0406a33bc687c731f9e7fedd56e1b07c3cc67))
|
||||
* **support:** update dependency teen_process to v2.1.4 ([96a7a3f](https://github.com/appium/appium/commit/96a7a3f23bead7c1d18700550138cd2d70ce5e3c))
|
||||
* **types:** update dependency type-fest to v4.19.0 ([#20193](https://github.com/appium/appium/issues/20193)) ([db62358](https://github.com/appium/appium/commit/db62358dbac25de2a75fdc7493338d98b1422c84))
|
||||
|
||||
|
||||
|
||||
## [4.2.6](https://github.com/appium/appium/compare/@appium/support@4.2.5...@appium/support@4.2.6) (2024-05-27)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @ts-check
|
||||
|
||||
import npmlog from 'npmlog';
|
||||
import globalLog from '@appium/logger';
|
||||
import _ from 'lodash';
|
||||
import {unleakString} from './util';
|
||||
import moment from 'moment';
|
||||
@@ -20,7 +20,7 @@ for (let level of LEVELS) {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import('npmlog').Logger} logger
|
||||
* @param {import('@appium/logger').Logger} logger
|
||||
*/
|
||||
function patchLogger(logger) {
|
||||
if (!logger.debug) {
|
||||
@@ -30,7 +30,7 @@ function patchLogger(logger) {
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {[import('npmlog').Logger, boolean]}
|
||||
* @returns {[import('@appium/logger').Logger, boolean]}
|
||||
*/
|
||||
function _getLogger() {
|
||||
// check if the user set the `_TESTING` or `_FORCE_LOGS` flag
|
||||
@@ -46,7 +46,7 @@ function _getLogger() {
|
||||
logger = mockLog;
|
||||
} else {
|
||||
// otherwise, either use the global, or a new `npmlog` object
|
||||
logger = global._global_npmlog || npmlog;
|
||||
logger = global._global_npmlog || globalLog;
|
||||
// The default value is 10000, which causes excessive memory usage
|
||||
logger.maxRecordSize = MAX_LOG_RECORDS_COUNT;
|
||||
}
|
||||
|
||||
@@ -172,13 +172,15 @@ class MJpegStream extends Writable {
|
||||
* the HTTP request itself. Then reset the state.
|
||||
*/
|
||||
stop() {
|
||||
if (!this.consumer) {
|
||||
return;
|
||||
if (this.consumer) {
|
||||
this.consumer.unpipe(this);
|
||||
}
|
||||
if (this.responseStream) {
|
||||
if (this.consumer) {
|
||||
this.responseStream.unpipe(this.consumer);
|
||||
}
|
||||
this.responseStream.destroy();
|
||||
}
|
||||
|
||||
this.responseStream.unpipe(this.consumer);
|
||||
this.consumer.unpipe(this);
|
||||
this.responseStream.destroy();
|
||||
this.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/support",
|
||||
"version": "4.2.6",
|
||||
"version": "4.3.0",
|
||||
"description": "Support libs used across appium packages",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -42,7 +42,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@appium/tsconfig": "^0.3.3",
|
||||
"@appium/types": "^0.18.0",
|
||||
"@appium/types": "^0.19.0",
|
||||
"@colors/colors": "1.6.0",
|
||||
"@types/archiver": "6.0.2",
|
||||
"@types/base64-stream": "1.0.5",
|
||||
@@ -52,14 +52,13 @@
|
||||
"@types/lockfile": "1.0.4",
|
||||
"@types/mv": "2.1.4",
|
||||
"@types/ncp": "2.0.8",
|
||||
"@types/npmlog": "7.0.0",
|
||||
"@types/pluralize": "0.0.33",
|
||||
"@types/semver": "7.5.8",
|
||||
"@types/shell-quote": "1.7.5",
|
||||
"@types/supports-color": "8.1.3",
|
||||
"@types/teen_process": "2.0.4",
|
||||
"@types/uuid": "9.0.8",
|
||||
"@types/which": "3.0.3",
|
||||
"@types/which": "3.0.4",
|
||||
"archiver": "7.0.1",
|
||||
"axios": "1.7.2",
|
||||
"base64-stream": "1.0.0",
|
||||
@@ -77,7 +76,6 @@
|
||||
"moment": "2.30.1",
|
||||
"mv": "2.1.1",
|
||||
"ncp": "2.0.0",
|
||||
"npmlog": "7.0.1",
|
||||
"opencv-bindings": "4.5.5",
|
||||
"pkg-dir": "5.0.0",
|
||||
"plist": "3.1.0",
|
||||
@@ -89,8 +87,8 @@
|
||||
"shell-quote": "1.8.1",
|
||||
"source-map-support": "0.5.21",
|
||||
"supports-color": "8.1.1",
|
||||
"teen_process": "2.1.3",
|
||||
"type-fest": "4.18.3",
|
||||
"teen_process": "2.1.4",
|
||||
"type-fest": "4.19.0",
|
||||
"uuid": "9.0.1",
|
||||
"which": "4.0.0",
|
||||
"yauzl": "3.1.3"
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [3.0.37](https://github.com/appium/appium/compare/@appium/test-support@3.0.36...@appium/test-support@3.0.37) (2024-06-06)
|
||||
|
||||
**Note:** Version bump only for package @appium/test-support
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [3.0.36](https://github.com/appium/appium/compare/@appium/test-support@3.0.35...@appium/test-support@3.0.36) (2024-05-27)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/test-support",
|
||||
"version": "3.0.36",
|
||||
"version": "3.0.37",
|
||||
"description": "A collection of test utilities used across Appium packages",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -45,7 +45,7 @@
|
||||
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@appium/support": "^4.2.6",
|
||||
"@appium/support": "^4.3.0",
|
||||
"@colors/colors": "1.6.0",
|
||||
"bluebird": "3.7.2",
|
||||
"lodash": "4.17.21",
|
||||
|
||||
@@ -3,6 +3,20 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [0.19.0](https://github.com/appium/appium/compare/@appium/types@0.18.0...@appium/types@0.19.0) (2024-06-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **appium:** Replace npmlog with the local fork ([#20190](https://github.com/appium/appium/issues/20190)) ([8915934](https://github.com/appium/appium/commit/8915934270243bfb46c4d104a098ce1cc481b0ff))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **types:** update dependency type-fest to v4.19.0 ([#20193](https://github.com/appium/appium/issues/20193)) ([db62358](https://github.com/appium/appium/commit/db62358dbac25de2a75fdc7493338d98b1422c84))
|
||||
|
||||
|
||||
|
||||
## [0.18.0](https://github.com/appium/appium/compare/@appium/types@0.17.0...@appium/types@0.18.0) (2024-05-27)
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type {Logger} from 'npmlog';
|
||||
import type {Logger} from '@appium/logger';
|
||||
|
||||
/**
|
||||
* A log prefix for {@linkcode AppiumLogger}
|
||||
@@ -9,19 +9,16 @@ export type AppiumLoggerPrefix = string | (() => string);
|
||||
|
||||
/**
|
||||
* Possible "log levels" for {@linkcode AppiumLogger}.
|
||||
*
|
||||
* Extracted from `npmlog`.
|
||||
*/
|
||||
export type AppiumLoggerLevel = 'silly' | 'verbose' | 'debug' | 'info' | 'http' | 'warn' | 'error';
|
||||
|
||||
/**
|
||||
* Describes the `npmlog`-based internal logger.
|
||||
*
|
||||
* @see https://npm.im/npmlog
|
||||
* Describes the internal logger.
|
||||
*/
|
||||
export interface AppiumLogger {
|
||||
/**
|
||||
* Returns the underlying `npmlog` {@link Logger}.
|
||||
* Returns the underlying `logger` {@link Logger}.
|
||||
* ! This method is designed for private usage.
|
||||
*/
|
||||
unwrap(): Logger;
|
||||
level: AppiumLoggerLevel;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@appium/types",
|
||||
"version": "0.18.0",
|
||||
"version": "0.19.0",
|
||||
"description": "Various type declarations used across Appium",
|
||||
"keywords": [
|
||||
"automation",
|
||||
@@ -41,9 +41,8 @@
|
||||
"@appium/schema": "^0.5.0",
|
||||
"@appium/tsconfig": "^0.3.3",
|
||||
"@types/express": "4.17.21",
|
||||
"@types/npmlog": "7.0.0",
|
||||
"@types/ws": "8.5.10",
|
||||
"type-fest": "4.18.3"
|
||||
"type-fest": "4.19.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
|
||||
|
||||
+4
-1
@@ -67,6 +67,9 @@
|
||||
},
|
||||
{
|
||||
"path": "packages/strongbox"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "packages/logger"
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user