Compare commits

...
Author SHA1 Message Date
Christopher Hiller 8a6a4ba7e7 chore: publish
- appium@2.0.0-rc.5
 - @appium/base-driver@9.3.15
 - @appium/base-plugin@2.2.15
 - @appium/doctor@2.0.21
 - @appium/docutils@0.4.4
 - @appium/driver-test-support@0.4.10
 - @appium/eslint-config-appium@8.0.4
 - @appium/fake-driver@5.2.6
 - @appium/fake-plugin@3.1.19
 - @appium/plugin-test-support@0.3.18
 - @appium/schema@0.3.1
 - @appium/support@4.1.2
 - @appium/test-support@3.0.20
 - @appium/types@0.13.2
2023-07-03 13:18:58 -07:00
Christopher Hiller 52b646c65b chore(typedoc-plugin-appium): update snapshots 2023-07-03 13:10:51 -07:00
Christopher Hiller 2b351705d4 fix(base-driver): pass thru all type args to ExternalDriver
- `core` module is now TS
- `constants` module is now TS
- export missing `W3C_ELEMENT_KEY`
- `JWProxy.command` returns `Promise<unknown>`.  deal with it
- updated some type tests
2023-07-03 13:10:51 -07:00
Christopher Hiller c13333bb97 fix(appium): type fixes for ts v5 2023-07-03 13:10:51 -07:00
Christopher Hiller 62f4244753 fix(types): update some more types to reflect reality
- added a `Protocol` type for some string constants
- `proxyRouteIsAvoided` optionally accepts a `body` arg
- `Core<C>.driverForSession` does not actually return something using type `C`.
- `ExternalDriver` passes thru all type args to `Driver`. this should be non-breaking
- `StringRecord` is more appropriate type for default driver settings
- `Constraints` should be readonly
2023-07-03 13:10:51 -07:00
Christopher Hiller 26eb766a79 chore(base-driver): actually run type tests 2023-07-03 13:10:51 -07:00
Christopher Hiller 679865ed2f fix(eslint-config-appium): remove prototype assignment warning 2023-07-03 13:10:51 -07:00
Christopher Hiller f1d768c62c chore: upgrade typescript
we need to stay at v5.0.x for now
2023-07-03 13:10:51 -07:00
Christopher Hiller d6cca5175c fix(types): separate the type of opts from initialOpts
A thing we know about the `opts` object passed in to a driver constructor is that it does _not_ contain caps.  This value is retained in `this.initialOpts`.  Upon session creation, it _does_ contain caps.

This adds a new type, `InitialOpts`, which is the first parameter to a driver.  In the future, it may accept a type argument, as currently any extension-specific options (defined via schema in `package.json`) are not typed.

Because `DriverOpts` is a superset of `InitialOpts`, this should not be a breaking change.
2023-07-03 13:10:51 -07:00
Christopher Hiller 3d614d6d41 fix(base-driver): allow subclass to define shape of settings object
The mixin approach prevented subclasses of BaseDriver from narrowing the type of `this.settings`.  Now, that's possible.

Also:
- removed an unused type argument from BD constructor
- and did some typedef aliasing
- remove unneeded type assertion from log mixin
2023-07-03 13:10:51 -07:00
Christopher Hiller ee9b2a30de fix(types): ensure return type of deleteSession can always be void
a type aliased to `void` is not the same as returning `void`, apparently.  this might be fixed in newer TS versions
2023-07-03 13:10:51 -07:00
Christopher Hiller e30ad0e88c chore(appium,types): remove some useless type arguments 2023-07-03 13:10:51 -07:00
Christopher Hiller 01061b2919 fix(types,base-driver): remove deviceName from base constraints
This cap was conflicting with constraints defined in subclasses.  Currently, it isn't possible to cleanly "override" constraints.  Given `deviceName` is not used anywhere within base-driver's source, this seems like a decent workaround for now.
2023-07-03 13:10:51 -07:00
Christopher Hiller 24e7aeca7d fix(types): fix signature of updateSettings 2023-07-03 13:10:51 -07:00
renovate[bot] ed1856d720 fix(support): update dependency semver to v7.5.3 2023-07-01 16:31:57 +00:00
renovate[bot] 757fbaaf42 chore(deps): update dependency @types/node to v18.16.19 2023-07-01 12:54:42 +00:00
renovate[bot] fdd2ac098d fix(doctor): update dependency appium-adb to v9.11.7 2023-07-01 10:44:15 +00:00
renovate[bot] 3906f7d1ca chore(docutils): update dependency mkdocs-material to v9.1.17 2023-06-30 22:01:32 +00:00
Christopher Hiller f09fbb64dc fix(appium): restrict address to ipv6/hostname (#18824)
This resolves #18716.

For whatever reason, `json-schema-to-typescript` needed `"type": "string"` in there.  See https://github.com/bcherny/json-schema-to-typescript/issues/528 for further discussion
2023-06-30 13:33:34 -07:00
Mykola Mokhnach 97fe159276 chore(appium): Improve the error message on config load error (#18829) 2023-06-30 20:35:17 +02:00
renovate[bot] cb145875c0 chore(deps): update commitlint monorepo to v17.6.6 2023-06-30 17:38:50 +00:00
renovate[bot] d75338f1c8 chore(deps): update eslint-related packages to v5.59.11 2023-06-30 13:19:49 +00:00
renovate[bot] 67e7140216 chore(deps): update dependency lint-staged to v13.2.3 2023-06-30 11:39:58 +00:00
Christopher Hiller 81256f8f90 chore(types): fix clean command 2023-06-29 17:09:25 -07:00
Christopher Hiller 0bbb25dfb4 chore(base-driver,driver-test-support): do not run basedriver e2e tests in parallel
also: rewrote event timings tests due to it being unclear which assertion actually failed. one assertion per test.
2023-06-29 17:09:25 -07:00
renovate[bot] 5263366744 chore(deps): update dependency json-schema-to-typescript to v13.0.2 2023-06-29 20:56:36 +00:00
Christopher Hiller 4ab2780978 chore: run eslint --fix on ts files before commit 2023-06-29 13:14:37 -07:00
Jonathan Lipps 58b71869d1 chore: publish
- appium@2.0.0-rc.4
 - @appium/base-driver@9.3.14
 - @appium/base-plugin@2.2.14
 - @appium/doctor@2.0.20
 - @appium/docutils@0.4.3
 - @appium/driver-test-support@0.4.9
 - @appium/fake-plugin@3.1.18
 - @appium/plugin-test-support@0.3.17
 - @appium/support@4.1.1
 - @appium/test-support@3.0.19
 - @appium/types@0.13.1
2023-06-29 11:17:15 -07:00
renovate[bot] 08a1f1be94 chore(deps): update definitelytyped 2023-06-28 10:12:12 +00:00
renovate[bot] b7cecfffb5 chore(workflows): update actions/checkout digest to c85c95e 2023-06-28 08:20:51 +00:00
Kazuaki Matsuo 52a755a913 fix(docutils): docs versioning and update latest (#18804)
* fix: docs versioning and update latest

* fix lint
2023-06-27 21:13:12 -07:00
Mykola Mokhnach 35e0012d8a chore(appium): Use the actual server address in the logged URL (#18809) 2023-06-27 12:59:55 +02:00
Jonathan Lipps ed20e00754 chore: publish
- appium@2.0.0-rc.3
 - @appium/base-driver@9.3.13
 - @appium/base-plugin@2.2.13
 - @appium/doctor@2.0.19
 - @appium/docutils@0.4.2
 - @appium/driver-test-support@0.4.8
 - @appium/fake-driver@5.2.5
 - @appium/fake-plugin@3.1.17
 - @appium/plugin-test-support@0.3.16
 - @appium/support@4.1.0
 - @appium/test-support@3.0.18
 - @appium/types@0.13.0
2023-06-15 13:57:59 -07:00
Christopher Hiller 9e60e80b13 chore(renovate): add get-stream to major upgrade ban list 2023-06-15 11:57:15 -07:00
Jonathan LippsandChristopher Hiller 1a5b8cca2d fix(docutils): set mike version to major.minor by default (#18770)
* fix(docutils): set mike version to major.minor by default

* Update packages/docutils/lib/builder/deploy.ts

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

---------

Co-authored-by: Christopher Hiller <boneskull@boneskull.com>
2023-06-15 10:19:05 -07:00
Mykola Mokhnach ced560206b ci: Update bug report template (#18766) 2023-06-15 06:30:23 +02:00
Christopher Hiller 7dbf6f2cd3 chore(typedoc-plugin-appium): update snapshots 2023-06-14 16:21:51 -07:00
Christopher Hiller 84c49b1529 chore(support): fix module paths in some tests 2023-06-14 16:21:51 -07:00
Christopher Hiller 81bc527be6 fix(types): various fixes for reality
- because BaseDriver implements `findElOrEls` (technically), any subclasses must not inherit an interface containing a non-identical `findElOrEls` -- not even narrowing.  so to avoid this, we will need to make it as broad as possible; no more generic `Ctx`
- likewise with `getLog`
- fix return type of `setGeoLocation`
- fix return type of `getPerformanceData`
- fix return type of `removeApp`
- fix return type of `hideKeyboard`
- fix return type of `getSystemBars`
- fix signature of various `touch*` methods
- fix return type of `setNetworkConnection`

alternatively, the deprecated methods mentioned here should be removed.
2023-06-14 16:21:51 -07:00
Christopher Hiller 2e909478e9 chore(types): remove unused interfaces
Both `StartScreenRecordOptions` and `StopScreenRecordOptions` are for deprecated core APIs and are defined individually by drivers
2023-06-14 16:21:51 -07:00
Christopher Hiller 00ae1625d7 fix(types,fake-driver): getLog doesn't necessarily return an array 2023-06-14 16:21:51 -07:00
Christopher Hiller 88293f8039 feat(support): export a bunch of types that weren't properly exported 2023-06-14 16:21:51 -07:00
Christopher Hiller 54a4a8da03 fix(base-driver): update def of findElOrEls and findElOrElsWithProcessing
- adds some types to the `Proxy` class
- make `isErrorType()` a proper type guard
2023-06-14 16:21:51 -07:00
Christopher Hiller 598b255e8d fix(fake-driver): update definition of findElOrEls 2023-06-14 16:21:51 -07:00
Christopher Hiller 63a5c22127 fix(types)!: use overload instead of broken conditional type in findElOrEls
BREAKING CHANGE: This changes the def of `findElOrEls` and `findElOrElsWithProcessing` in `ExternalDriver` in a breaking manner.

So conditional types don't work like how I was using them.  They work in capital-T-types (`type`), but they don't work as return values.  Instead, what we should have is an overload.  in this case, the function can be called one of two ways, and it returns a different thing depending on those values.  _unfortunately_ this is a little hinky to implement, given that overloads are unsupported in _object literals_.  they are supported in function statements or expressions, and they are supported in class definitions, but not object literals.  you'll see what needs to happen to make this work in `FakeDriver` and `BaseDriver` in subsequent changesets; essentially the function must be defined outside of the object literal and then stuffed in there.

The other change here changes an `object` type (which does not allow arbitrary properties) to a `StringRecord` type within the type which converts `Constraints` to `Capabilities`.  This affects caps for some drivers such as `chromedriverArgs` in `appium-android-driver`; anywhere where the constraint has `isObject: true`.
2023-06-14 16:21:51 -07:00
Jonathan Lipps af066eb5c3 chore: publish
- appium@2.0.0-rc.2
 - @appium/base-driver@9.3.12
 - @appium/base-plugin@2.2.12
 - @appium/doctor@2.0.18
 - @appium/docutils@0.4.1
 - @appium/fake-plugin@3.1.16
 - @appium/support@4.0.3
 - @appium/test-support@3.0.17
2023-06-14 11:21:00 -07:00
Christopher Hiller e5254b5b45 fix(docutils): fixes some weirdness with default behavior and the "implies" keyword (#18751)
* fix(docutils): fixes some weirdness with default behavior and the "implies" keyword

- also squashes an errrant warning
- fix some diff logic when writing to `mkdocs.yml`

* fix(docutils): more robust mike-finding
2023-06-14 11:18:55 -07:00
Mykola Mokhnach c18eb03261 fix(support): Require the optional sharp dep properly from mjpeg module (#18769) 2023-06-14 20:17:25 +02:00
86 changed files with 1836 additions and 1040 deletions
+21 -9
View File
@@ -6,6 +6,20 @@ body:
- type: markdown
attributes:
value: ':stop_sign: _For support questions, please visit [http://discuss.appium.io](http://discuss.appium.io) instead._'
- type: checkboxes
attributes:
label: 'Do I have the most recent component updates?'
description: 'Appium 1-related issues are going to be ignored as this version has reached its end of life.'
options:
- label: 'I use the most recent available driver/plugin and server versions'
required: true
- type: checkboxes
attributes:
label: 'Is the component officially supported by the Appium team?'
description: 'Make sure you report an issue for a component which is officially supported/maintained by the Appium team.'
options:
- label: 'I have verified the component repository is present under the Appium organization in GitHub'
required: true
- type: checkboxes
attributes:
label: 'Is there an existing issue for this?'
@@ -34,7 +48,7 @@ body:
An easy way to get started is to copy [sample code](https://github.com/appium/appium/tree/master/packages/appium/sample-code) and modify it accordingly.
If the result is more than a screenful of text _or_ requires multiple files, please:
- _Attach_ (do not paste) it to this textarea, _or_
- Put it in a [Gist](https://gist.github.com) and paste the link, _or_
- Provide a link to a new or existing public repository exhibiting the issue
@@ -46,14 +60,12 @@ body:
description: 'Please provide the following information about your environment; feel free to remove any items which are not relevant.'
value: |
- Operating system:
- If running via `appium` CLI...
- Appium CLI version (output of `appium --version`):
- Node.js version (output of `node --version`):
- `npm` version (output of `npm --version`):
- Last `appium` version which did _not_ exhibit the problem:
- If running Appium Desktop, its version:
- Appium server version (output of `appium --version`):
- Appium driver(s) and their version(s):
- Appium plugin(s) and their version(s):
- Node.js version (output of `node --version`):
- `npm` version (output of `npm --version`):
- Last component(s) version which did _not_ exhibit the problem:
- Platform and version under test:
- Real device or emulator/simulator:
validations:
@@ -63,9 +75,9 @@ body:
label: 'Link to Appium Logs'
description: |
Create a [Gist](https://gist.github.com)—which contains your _full_ Appium logs—and link it here. Alternatively, you can attach a logfile to this issue (drag it into the "Further Information" field below).
:warning: _Remember to redact or remove any sensitive information!_
placeholder: 'https://gist.github.com/...'
placeholder: 'https://gist.github.com/...'
- type: textarea
attributes:
label: Futher Information
+2 -2
View File
@@ -54,7 +54,7 @@ jobs:
# - macos-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
@@ -82,7 +82,7 @@ jobs:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
- name: Install dependencies
uses: bahmutov/npm-install@1a235c31658a322a3b024444759650ee6345c26d # tag=v1
with:
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
- name: Cleanup
run: |
+1 -1
View File
@@ -35,7 +35,7 @@ jobs:
name: Docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
- name: Install dependencies (Node.js)
uses: bahmutov/npm-install@1a235c31658a322a3b024444759650ee6345c26d # tag=v1
with:
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
name: Run FOSSA Analysis
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
with:
ref: master
- name: Install dependencies
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
name: Check Renovate Configs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
- name: Validate Renovate Config
uses: rinchsan/renovate-config-validator@1ea1e8514f6a33fdd71c40b0a5fa3512b9e7b936 # tag=v0
with:
+1 -2
View File
@@ -1,6 +1,5 @@
module.exports = {
'*.js': ['eslint --fix', 'prettier --write'],
'*.ts': ['prettier --write'],
'*.(js|ts)': ['eslint --fix', 'prettier --write'],
'appium-config-schema.js': () => [
'npm run --workspace=./packages/schema build',
'git add -A packages/schema/lib/appium-config.schema.json',
+633 -320
View File
File diff suppressed because it is too large Load Diff
+10 -9
View File
@@ -85,22 +85,23 @@
},
"devDependencies": {
"@colors/colors": "1.5.0",
"@commitlint/cli": "17.6.5",
"@commitlint/config-conventional": "17.6.5",
"@commitlint/cli": "17.6.6",
"@commitlint/config-conventional": "17.6.6",
"@tsconfig/node14": "1.0.3",
"@types/chai": "4.3.5",
"@types/chai-as-promised": "7.1.5",
"@types/diff": "5.0.3",
"@types/mocha": "10.0.1",
"@types/node": "18.16.16",
"@types/node": "18.16.19",
"@types/semver": "7.5.0",
"@types/sinon": "10.0.15",
"@types/sinon-chai": "3.2.9",
"@types/source-map-support": "0.5.6",
"@types/teen_process": "2.0.0",
"@types/ws": "8.5.4",
"@types/ws": "8.5.5",
"@types/yargs": "17.0.24",
"@typescript-eslint/eslint-plugin": "5.59.8",
"@typescript-eslint/parser": "5.59.8",
"@typescript-eslint/eslint-plugin": "5.59.11",
"@typescript-eslint/parser": "5.59.11",
"asyncbox": "2.9.4",
"chai": "4.3.7",
"chai-as-promised": "7.1.1",
@@ -119,9 +120,9 @@
"get-port": "5.1.1",
"handlebars": "4.7.7",
"husky": "8.0.3",
"json-schema-to-typescript": "13.0.1",
"json-schema-to-typescript": "13.0.2",
"lerna": "6.6.2",
"lint-staged": "13.2.2",
"lint-staged": "13.2.3",
"log-symbols": "4.1.0",
"midnight-smoker": "2.0.4",
"mjpeg-consumer": "2.0.0",
@@ -142,7 +143,7 @@
"typedoc": "0.23.28",
"typedoc-plugin-markdown": "3.14.0",
"typedoc-plugin-resolve-crossmodule-references": "0.3.3",
"typescript": "4.9.5",
"typescript": "5.0.4",
"validate.js": "0.13.1",
"webdriverio": "7.31.1",
"ws": "8.13.0",
+35
View File
@@ -3,6 +3,41 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.0.0-rc.5](https://github.com/appium/appium/compare/appium@2.0.0-rc.4...appium@2.0.0-rc.5) (2023-07-03)
### Bug Fixes
* **appium:** restrict address to ipv6/hostname ([#18824](https://github.com/appium/appium/issues/18824)) ([f09fbb6](https://github.com/appium/appium/commit/f09fbb64dce0e179a007f3a0ae9800e61fbe90eb)), closes [#18716](https://github.com/appium/appium/issues/18716)
* **appium:** type fixes for ts v5 ([c13333b](https://github.com/appium/appium/commit/c13333bb979ee3409e6a62a5800c629781553b42))
* **support:** update dependency semver to v7.5.3 ([ed1856d](https://github.com/appium/appium/commit/ed1856d720c442842d5c3fe5f6caeccb8229b5f1))
## [2.0.0-rc.4](https://github.com/appium/appium/compare/appium@2.0.0-rc.3...appium@2.0.0-rc.4) (2023-06-29)
**Note:** Version bump only for package appium
## [2.0.0-rc.3](https://github.com/appium/appium/compare/appium@2.0.0-rc.2...appium@2.0.0-rc.3) (2023-06-15)
**Note:** Version bump only for package appium
## [2.0.0-rc.2](https://github.com/appium/appium/compare/appium@2.0.0-rc.1...appium@2.0.0-rc.2) (2023-06-14)
**Note:** Version bump only for package appium
## [2.0.0-rc.1](https://github.com/appium/appium/compare/appium@2.0.0-beta.71...appium@2.0.0-rc.1) (2023-06-14)
+1 -1
View File
@@ -163,7 +163,7 @@ class AppiumDriver extends DriverCore {
async getSessions() {
return _.toPairs(this.sessions).map(([id, driver]) => ({
id,
capabilities: /** @type {import('@appium/types').DriverCaps} */ (driver.caps),
capabilities: /** @type {import('@appium/types').DriverCaps<any>} */ (driver.caps),
}));
}
+10 -2
View File
@@ -9,7 +9,11 @@ import {getSchema, validate} from './schema/schema';
* @type {import('lilconfig').LoaderSync}
*/
function yamlLoader(filepath, content) {
return yaml.parse(content);
try {
return yaml.parse(content);
} catch (e) {
throw new Error(`The YAML config at '${filepath}' cannot be loaded. Original error: ${e.message}`);
}
}
/**
@@ -27,7 +31,11 @@ const rawConfig = new Map();
*/
function jsonLoader(filepath, content) {
rawConfig.set(filepath, content);
return JSON.parse(content);
try {
return JSON.parse(content);
} catch (e) {
throw new Error(`The JSON config at '${filepath}' cannot be loaded. Original error: ${e.message}`);
}
}
/**
+10 -2
View File
@@ -284,7 +284,11 @@ export class Manifest {
...internal,
};
if (!_.isEqual(value, this.#data.drivers[pkgJson.appium.driverName])) {
this.setExtension(DRIVER_TYPE, pkgJson.appium.driverName, value);
this.setExtension(
/** @type {ExtType} */ (DRIVER_TYPE),
pkgJson.appium.driverName,
/** @type {ExtManifest<ExtType>} */ (value)
);
return true;
}
return false;
@@ -294,7 +298,11 @@ export class Manifest {
...internal,
};
if (!_.isEqual(value, this.#data.plugins[pkgJson.appium.pluginName])) {
this.setExtension(PLUGIN_TYPE, pkgJson.appium.pluginName, value);
this.setExtension(
/** @type {ExtType} */ (PLUGIN_TYPE),
pkgJson.appium.pluginName,
/** @type {ExtManifest<ExtType>} */ (value)
);
return true;
}
return false;
+21 -9
View File
@@ -2,7 +2,11 @@
import {init as logsinkInit} from './logsink'; // this import needs to come first since it sets up global npmlog
import logger from './logger'; // logger needs to remain second
import {routeConfiguringFunction as makeRouter, server as baseServer} from '@appium/base-driver';
import {
routeConfiguringFunction as makeRouter,
server as baseServer,
normalizeBasePath,
} from '@appium/base-driver';
import {logger as logFactory, util, env, fs} from '@appium/support';
import {asyncify} from 'asyncbox';
import _ from 'lodash';
@@ -32,11 +36,12 @@ import {
isExtensionCommandArgs,
isPluginCommandArgs,
isServerCommandArgs,
fetchIpAddresses,
fetchInterfaces,
V4_BROADCAST_IP,
V6_BROADCAST_IP,
} from './utils';
import os from 'node:os';
import net from 'node:net';
const {resolveAppiumHome} = env;
@@ -328,17 +333,23 @@ async function init(args) {
* @param {string} url The URL the server is listening on
*/
function logServerAddress(url) {
logger.info(`Appium REST http interface listener started on ${url}`);
const urlObj = new URL(url);
if (![V4_BROADCAST_IP, V6_BROADCAST_IP].includes(urlObj.hostname)) {
logger.info(`Appium REST http interface listener started on ${url}`);
if (![V4_BROADCAST_IP, V6_BROADCAST_IP, `[${V6_BROADCAST_IP}]`].includes(urlObj.hostname)) {
return;
}
const ips = fetchIpAddresses(urlObj.hostname === V4_BROADCAST_IP ? 4 : 6);
const interfaces = fetchInterfaces(urlObj.hostname === V4_BROADCAST_IP ? 4 : 6);
const toLabel = (/** @type {os.NetworkInterfaceInfo} */ iface) => {
const href = urlObj.href.replace(urlObj.hostname, iface.address);
return iface.internal
? `${href} (only accessible from the same host)`
: href;
};
logger.info(
`You can provide the following ${util.pluralize('URL', ips.length, false)} ` +
`in your client code to connect to this server:\n` +
ips.map((x) => `\t${urlObj.href.replace(urlObj.hostname, x)}`).join('\n')
`You can provide the following ${util.pluralize('URL', interfaces.length, false)} ` +
`in your client code to connect to this server:\n` +
interfaces.map((iface) => `\t${toLabel(iface)}`).join('\n')
);
}
@@ -442,7 +453,8 @@ async function main(args) {
});
}
logServerAddress(`http://${parsedArgs.address}:${parsedArgs.port}${parsedArgs.basePath}`);
const address = net.isIPv6(parsedArgs.address) ? `[${parsedArgs.address}]` : parsedArgs.address;
logServerAddress(`http://${address}:${parsedArgs.port}${normalizeBasePath(parsedArgs.basePath)}`);
driverConfig.print();
pluginConfig.print([...pluginClasses.values()]);
+5 -6
View File
@@ -336,13 +336,13 @@ export function isPluginCommandArgs(args) {
}
/**
* Fetches the list of IP addresses of the current host.
* Fetches the list of matched network interfaces of the current host.
*
* @param {4|6|null} family Either 4 to include ipv4 addresses only,
* 6 to include ipv6 addresses only, or null to include all of them
* @returns {string[]} The list of matched IP addresses
* @returns {os.NetworkInterfaceInfo[]} The list of matched interfcaes
*/
export function fetchIpAddresses (family = null) {
export function fetchInterfaces (family = null) {
let familyValue = null;
// 'IPv4' is in Node <= 17, from 18 it's a number 4 or 6
if (family === 4) {
@@ -350,11 +350,10 @@ export function fetchIpAddresses (family = null) {
} else if (family === 6) {
familyValue = [6, 'IPv6'];
}
// @ts-ignore The linter does not understand the below filter
return _.flatMap(_.values(os.networkInterfaces()).filter(Boolean))
// @ts-ignore The linter does not understand the above filter
.filter(({family}) => !familyValue || familyValue && familyValue.includes(family))
// @ts-ignore The linter does not understand the above filter
.map(({address}) => address);
.filter(({family}) => !familyValue || familyValue && familyValue.includes(family));
}
export {
+8 -8
View File
@@ -1,6 +1,6 @@
{
"name": "appium",
"version": "2.0.0-rc.1",
"version": "2.0.0-rc.5",
"description": "Automation for Apps.",
"keywords": [
"automation",
@@ -60,12 +60,12 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/base-driver": "^9.3.11",
"@appium/base-plugin": "^2.2.11",
"@appium/docutils": "^0.4.0",
"@appium/schema": "^0.3.0",
"@appium/support": "^4.0.2",
"@appium/types": "^0.12.0",
"@appium/base-driver": "^9.3.15",
"@appium/base-plugin": "^2.2.15",
"@appium/docutils": "^0.4.4",
"@appium/schema": "^0.3.1",
"@appium/support": "^4.1.2",
"@appium/types": "^0.13.2",
"@sidvind/better-ajv-errors": "2.1.0",
"@types/argparse": "2.0.10",
"@types/bluebird": "3.5.38",
@@ -89,7 +89,7 @@
"ora": "5.4.1",
"package-changed": "3.0.0",
"resolve-from": "5.0.0",
"semver": "7.5.1",
"semver": "7.5.3",
"source-map-support": "0.5.21",
"teen_process": "2.0.2",
"type-fest": "3.11.1",
@@ -320,7 +320,7 @@ describe('config file behavior', function () {
return this.skip();
}
await readConfigFile(INVALID_JSON_FILEPATH).should.be.rejectedWith(
new RegExp(`${INVALID_JSON_FILEPATH} is invalid`)
new RegExp(`${_.escapeRegExp(INVALID_JSON_FILEPATH)}`)
);
});
});
+4
View File
@@ -16,6 +16,10 @@ export default [
description: 'IPv4/IPv6 address or a hostname to listen on',
title: 'address config',
type: 'string',
anyOf: [
{format: 'hostname', type: 'string'},
{format: 'ipv6', type: 'string'}
]
},
},
{
+8 -8
View File
@@ -5,7 +5,7 @@ import {
removeAppiumPrefixes,
inspect,
adjustNodePath,
fetchIpAddresses,
fetchInterfaces,
} from '../../lib/utils';
import {BASE_CAPS, W3C_CAPS} from '../helpers';
import _ from 'lodash';
@@ -277,17 +277,17 @@ describe('utils', function () {
});
});
describe('fetchIpAddresses()', function () {
it('should fetch addresses for ipv4 only', async function () {
fetchIpAddresses(4).length.should.be.greaterThan(0);
describe('fetchInterfaces()', function () {
it('should fetch interfaces for ipv4 only', async function () {
fetchInterfaces(4).length.should.be.greaterThan(0);
});
it('should fetch addresses for ipv6 only', async function () {
fetchIpAddresses(6).length.should.be.greaterThan(0);
it('should fetch interfaces for ipv6 only', async function () {
fetchInterfaces(6).length.should.be.greaterThan(0);
});
it('should fetch addresses for ipv4 and ipv6', async function () {
fetchIpAddresses().length.should.be.greaterThan(0);
it('should fetch interfaces for ipv4 and ipv6', async function () {
fetchInterfaces().length.should.be.greaterThan(0);
});
});
+38
View File
@@ -3,6 +3,44 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [9.3.15](https://github.com/appium/appium/compare/@appium/base-driver@9.3.14...@appium/base-driver@9.3.15) (2023-07-03)
### Bug Fixes
* **base-driver:** allow subclass to define shape of settings object ([3d614d6](https://github.com/appium/appium/commit/3d614d6d414d0d34026f516dbfad7d296000efcf))
* **base-driver:** pass thru all type args to ExternalDriver ([2b35170](https://github.com/appium/appium/commit/2b351705d401e2db8da76022989c1475cbdda0f8))
* **types,base-driver:** remove deviceName from base constraints ([01061b2](https://github.com/appium/appium/commit/01061b291981333bdec59adfbea60f0cef3d69c1))
* **types:** separate the type of opts from initialOpts ([d6cca51](https://github.com/appium/appium/commit/d6cca5175c3e55d4670936c9d216cd3a6610d16b))
## [9.3.14](https://github.com/appium/appium/compare/@appium/base-driver@9.3.13...@appium/base-driver@9.3.14) (2023-06-29)
**Note:** Version bump only for package @appium/base-driver
## [9.3.13](https://github.com/appium/appium/compare/@appium/base-driver@9.3.12...@appium/base-driver@9.3.13) (2023-06-15)
### Bug Fixes
* **base-driver:** update def of findElOrEls and findElOrElsWithProcessing ([54a4a8d](https://github.com/appium/appium/commit/54a4a8da030dbecde783168bb92634df837d5a41))
* **types:** various fixes for reality ([81bc527](https://github.com/appium/appium/commit/81bc527be6aa54dd30a012156b5752b8b821ac0c))
## [9.3.12](https://github.com/appium/appium/compare/@appium/base-driver@9.3.11...@appium/base-driver@9.3.12) (2023-06-14)
**Note:** Version bump only for package @appium/base-driver
## [9.3.11](https://github.com/appium/appium/compare/@appium/base-driver@9.3.10...@appium/base-driver@9.3.11) (2023-06-14)
@@ -1,4 +1,5 @@
import {Constraints, IFindCommands} from '@appium/types';
/* eslint-disable @typescript-eslint/no-unused-vars */
import {Constraints, Element, IFindCommands} from '@appium/types';
import {errors} from '../../protocol';
import {BaseDriver} from '../driver';
import {mixin} from './mixin';
@@ -8,6 +9,67 @@ declare module '../driver' {
interface BaseDriver<C extends Constraints> extends IFindCommands {}
}
async function findElOrEls<C extends Constraints>(
this: BaseDriver<C>,
strategy: string,
selector: string,
mult: true,
context?: any
): Promise<Element[]>;
async function findElOrEls<C extends Constraints>(
this: BaseDriver<C>,
strategy: string,
selector: string,
mult: false,
context?: any
): Promise<Element>;
async function findElOrEls<C extends Constraints>(
this: BaseDriver<C>,
strategy: string,
selector: string,
mult: boolean,
context?: any
): Promise<Element[] | Element> {
throw new errors.NotImplementedError('Not implemented yet for find.');
}
async function findElOrElsWithProcessing<C extends Constraints>(
this: BaseDriver<C>,
strategy: string,
selector: string,
mult: true,
context?: any
): Promise<Element[]>;
async function findElOrElsWithProcessing<C extends Constraints>(
this: BaseDriver<C>,
strategy: string,
selector: string,
mult: false,
context?: any
): Promise<Element>;
async function findElOrElsWithProcessing<C extends Constraints>(
this: BaseDriver<C>,
strategy: string,
selector: string,
mult: boolean,
context?: any
): Promise<Element[] | Element> {
this.validateLocatorStrategy(strategy);
try {
// @ts-expect-error TS does not understand how to deal with the overload here
return await this.findElOrEls(strategy, selector, mult, context);
} catch (err) {
if (this.opts.printPageSourceOnFindFailure) {
const src = await this.getPageSource();
this.log.debug(`Error finding element${mult ? 's' : ''}: ${err.message}`);
this.log.debug(`Page source requested through 'printPageSourceOnFindFailure':`);
this.log.debug(src);
}
// still want the error to occur
throw err;
}
}
const FindCommands: IFindCommands = {
async findElement<C extends Constraints>(this: BaseDriver<C>, strategy, selector) {
return await this.findElOrElsWithProcessing(strategy, selector, false);
@@ -35,46 +97,13 @@ const FindCommands: IFindCommands = {
return await this.findElOrElsWithProcessing(strategy, selector, true, elementId);
},
/**
* Returns an object which adheres to the way the JSON Wire Protocol represents elements:
*
* Override this for your own driver!
*/
async findElOrEls<C extends Constraints, Mult extends boolean, Ctx = any>(
this: BaseDriver<C>,
strategy: string,
selector: string,
mult: Mult,
context: Ctx
) {
throw new errors.NotImplementedError('Not implemented yet for find.');
},
findElOrEls,
async getPageSource<C extends Constraints>(this: BaseDriver<C>) {
throw new errors.NotImplementedError('Not implemented yet for find.');
},
async findElOrElsWithProcessing<C extends Constraints, Mult extends boolean, Ctx = any>(
this: BaseDriver<C>,
strategy: string,
selector: string,
mult: Mult,
context?: Ctx
) {
this.validateLocatorStrategy(strategy);
try {
return await this.findElOrEls(strategy, selector, mult, context);
} catch (err) {
if (this.opts.printPageSourceOnFindFailure) {
const src = await this.getPageSource();
this.log.debug(`Error finding element${mult ? 's' : ''}: ${err.message}`);
this.log.debug(`Page source requested through 'printPageSourceOnFindFailure':`);
this.log.debug(src);
}
// still want the error to occur
throw err;
}
},
findElOrElsWithProcessing,
};
mixin(FindCommands);
@@ -1,6 +1,5 @@
import './event';
import './find';
import './log';
import './settings';
import './timeout';
import './execute';
@@ -1,6 +1,6 @@
import {Constraints, Driver, ILogCommands, LogDefRecord} from '@appium/types';
import type {Constraints, Driver, ILogCommands} from '@appium/types';
import _ from 'lodash';
import {BaseDriver} from '../driver';
import type {BaseDriver} from '../driver';
import {mixin} from './mixin';
declare module '../driver' {
@@ -9,7 +9,7 @@ declare module '../driver' {
}
const LogCommands: ILogCommands = {
supportedLogTypes: <LogDefRecord>{},
supportedLogTypes: {},
async getLogTypes<C extends Constraints>(this: BaseDriver<C>) {
this.log.debug('Retrieving supported log types');
@@ -1,26 +0,0 @@
import {BaseDriver} from '../driver';
import {Constraints, ISettingsCommands, StringRecord} from '@appium/types';
import {mixin} from './mixin';
declare module '../driver' {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface BaseDriver<C extends Constraints> extends ISettingsCommands {}
}
const SettingsCommands: ISettingsCommands = {
async updateSettings<C extends Constraints>(this: BaseDriver<C>, newSettings: StringRecord) {
if (!this.settings) {
this.log.errorAndThrow('Cannot update settings; settings object not found');
}
return await this.settings.update(newSettings);
},
async getSettings<C extends Constraints>(this: BaseDriver<C>) {
if (!this.settings) {
this.log.errorAndThrow('Cannot get settings; settings object not found');
}
return this.settings.getSettings();
},
};
mixin(SettingsCommands);
@@ -2,10 +2,23 @@
/* eslint-disable require-await */
import {logger} from '@appium/support';
import type {
AppiumLogger,
Constraints,
Core,
Driver,
DriverOpts,
EventHistory,
HTTPMethod,
InitialOpts,
Protocol,
RouteMatcher,
StringRecord,
} from '@appium/types';
import AsyncLock from 'async-lock';
import {EventEmitter} from 'events';
import _ from 'lodash';
import os from 'os';
import {EventEmitter} from 'node:events';
import os from 'node:os';
import {DEFAULT_BASE_PATH, PROTOCOLS} from '../constants';
import {errors} from '../protocol';
import DeviceSettings from './device-settings';
@@ -15,35 +28,22 @@ const NEW_COMMAND_TIMEOUT_MS = 60 * 1000;
const ON_UNEXPECTED_SHUTDOWN_EVENT = 'onUnexpectedShutdown';
/**
* @template {Constraints} C
* @template {StringRecord} [Settings=StringRecord]
* @implements {Core<C, Settings>}
*/
class DriverCore {
export class DriverCore<const C extends Constraints, Settings extends StringRecord = StringRecord>
implements Core<C, Settings>
{
/**
* Make the basedriver version available so for any driver which inherits from this package, we
* know which version of basedriver it inherited from
*/
static baseVersion = BASEDRIVER_VER;
/**
* @type {string?}
*/
sessionId;
sessionId: string | null;
/**
* @type {import('@appium/types').DriverOpts<C>}
*/
opts;
opts: DriverOpts<C>;
/**
* @type {import('@appium/types').DriverOpts<C>}
*/
initialOpts;
initialOpts: InitialOpts;
/** @type {typeof helpers} */
helpers;
helpers: typeof helpers;
/**
* basePath is used for several purposes, for example in setting up
@@ -52,83 +52,58 @@ class DriverCore {
* initially but it is automatically updated during any actual program
* execution by the routeConfiguringFunction, which is necessarily run as
* the entrypoint for any Appium server
* @type {string}
*/
basePath;
basePath: string;
/** @type {boolean} */
relaxedSecurityEnabled;
relaxedSecurityEnabled: boolean;
/** @type {string[]} */
allowInsecure;
allowInsecure: string[];
/** @type {string[]} */
denyInsecure;
denyInsecure: string[];
/** @type {number} */
newCommandTimeoutMs;
newCommandTimeoutMs: number;
/** @type {number} */
implicitWaitMs;
implicitWaitMs: number;
/** @type {string[]} */
locatorStrategies;
locatorStrategies: string[];
/** @type {string[]} */
webLocatorStrategies;
webLocatorStrategies: string[];
/** @type {Driver[]} */
managedDrivers;
managedDrivers: Driver[];
/** @type {NodeJS.Timeout?} */
noCommandTimer;
noCommandTimer: NodeJS.Timeout | null;
/** @type {EventHistory} */
_eventHistory;
protected _eventHistory: EventHistory;
// used to handle driver events
/** @type {NodeJS.EventEmitter} */
eventEmitter;
eventEmitter: NodeJS.EventEmitter;
/**
* @type {AppiumLogger}
* @privateRemarks XXX: unsure why this is wrapped in a getter when nothing else is
*/
_log;
protected _log: AppiumLogger;
/**
* @type {boolean}
*/
shutdownUnexpectedly;
shutdownUnexpectedly: boolean;
/**
* @type {boolean}
*/
shouldValidateCaps;
shouldValidateCaps: boolean;
/**
* @protected
* @type {AsyncLock}
*/
commandsQueueGuard;
protected commandsQueueGuard: AsyncLock;
/**
* settings should be instantiated by drivers which extend BaseDriver, but
* we set it to an empty DeviceSettings instance here to make sure that the
* default settings are applied even if an extending driver doesn't utilize
* the settings functionality itself
* @type {DeviceSettings<Settings>}
*/
settings;
settings: DeviceSettings<Settings>;
/**
* @param {DriverOpts<C>} opts
* @param {boolean} [shouldValidateCaps]
*/
constructor(opts = /** @type {DriverOpts<C>} */ ({}), shouldValidateCaps = true) {
this._log = logger.getLogger(helpers.generateDriverLogPrefix(this));
protocol?: Protocol;
constructor(opts: InitialOpts = <InitialOpts>{}, shouldValidateCaps = true) {
this._log = logger.getLogger(helpers.generateDriverLogPrefix(this as Core<C>));
// setup state
this.opts = opts;
this.opts = opts as DriverOpts<C>;
// use a custom tmp dir to avoid losing data and app when computer is
// restarted
@@ -168,11 +143,11 @@ class DriverCore {
* when the driver is shut down unexpectedly. Multiple calls to this method
* will cause the handler to be executed mutiple times
*
* @param {(...args: any[]) => void} handler The code to be executed on unexpected shutdown.
* @param handler The code to be executed on unexpected shutdown.
* The function may accept one argument, which is the actual error instance, which
* caused the driver to shut down.
*/
onUnexpectedShutdown(handler) {
onUnexpectedShutdown(handler: (...args: any[]) => void) {
this.eventEmitter.on(ON_UNEXPECTED_SHUTDOWN_EVENT, handler);
}
@@ -183,7 +158,7 @@ class DriverCore {
* Override it in inherited driver classes if necessary.
*/
get driverData() {
return /** @type {import('@appium/types').DriverData} */ ({});
return {};
}
/**
@@ -191,13 +166,13 @@ class DriverCore {
* handles new driver commands received from the client.
* Override it for inherited classes only in special cases.
*
* @return {boolean} If the returned value is true (default) then all the commands
* @return If the returned value is true (default) then all the commands
* received by the particular driver instance are going to be put into the queue,
* so each following command will not be executed until the previous command
* execution is completed. False value disables that queue, so each driver command
* is executed independently and does not wait for anything.
*/
get isCommandsQueueEnabled() {
get isCommandsQueueEnabled(): boolean {
return true;
}
@@ -211,9 +186,8 @@ class DriverCore {
/**
* API method for driver developers to log timings for important events
* @param {string} eventName
*/
logEvent(eventName) {
logEvent(eventName: string) {
if (eventName === 'commands') {
throw new Error('Cannot log commands directly');
}
@@ -240,10 +214,8 @@ class DriverCore {
/**
* method required by MJSONWP in order to determine whether it should
* respond with an invalid session response
* @param {string} [sessionId]
* @returns {boolean}
*/
sessionExists(sessionId) {
sessionExists(sessionId: string): boolean {
if (!sessionId) return false; // eslint-disable-line curly
return sessionId === this.sessionId;
}
@@ -251,11 +223,9 @@ class DriverCore {
/**
* method required by MJSONWP in order to determine if the command should
* be proxied directly to the driver
* @param {string} sessionId
* @returns {Core<C> | null}
*/
driverForSession(sessionId) {
return /** @type {Core<C> | null} */ (this);
driverForSession(sessionId: string): Core<Constraints> | null {
return this as Core<Constraints>;
}
isMjsonwpProtocol() {
@@ -277,11 +247,9 @@ class DriverCore {
/**
* Check whether a given feature is enabled via its name
*
* @param {string} name - name of feature/command
*
* @returns {Boolean}
* @param name - name of feature/command
*/
isFeatureEnabled(name) {
isFeatureEnabled(name: string): boolean {
// if we have explicitly denied this feature, return false immediately
if (this.denyInsecure && _.includes(this.denyInsecure, name)) {
return false;
@@ -306,10 +274,10 @@ class DriverCore {
* Assert that a given feature is enabled and throw a helpful error if it's
* not
*
* @param {string} name - name of feature/command
* @param name - name of feature/command
* @deprecated
*/
ensureFeatureEnabled(name) {
ensureFeatureEnabled(name: string) {
this.assertFeatureEnabled(name);
}
@@ -317,9 +285,9 @@ class DriverCore {
* Assert that a given feature is enabled and throw a helpful error if it's
* not
*
* @param {string} name - name of feature/command
* @param name - name of feature/command
*/
assertFeatureEnabled(name) {
assertFeatureEnabled(name: string) {
if (!this.isFeatureEnabled(name)) {
throw new Error(
`Potentially insecure feature '${name}' has not been ` +
@@ -331,12 +299,7 @@ class DriverCore {
}
}
/**
*
* @param {string} strategy
* @param {boolean} [webContext]
*/
validateLocatorStrategy(strategy, webContext = false) {
validateLocatorStrategy(strategy: string, webContext = false) {
let validStrategies = this.locatorStrategies;
this.log.debug(`Valid locator strategies for this request: ${validStrategies.join(', ')}`);
@@ -351,30 +314,15 @@ class DriverCore {
}
}
/**
*
* @param {string} [sessionId]
* @returns {boolean}
*/
proxyActive(sessionId) {
proxyActive(sessionId: string): boolean {
return false;
}
/**
*
* @param {string} sessionId
* @returns {import('@appium/types').RouteMatcher[]}
*/
getProxyAvoidList(sessionId) {
getProxyAvoidList(sessionId: string): RouteMatcher[] {
return [];
}
/**
*
* @param {string} [sessionId]
* @returns {boolean}
*/
canProxy(sessionId) {
canProxy(sessionId: string): boolean {
return false;
}
@@ -382,28 +330,28 @@ class DriverCore {
* Whether a given command route (expressed as method and url) should not be
* proxied according to this driver
*
* @param {string} sessionId - the current sessionId (in case the driver runs
* @param sessionId - the current sessionId (in case the driver runs
* multiple session ids and requires it). This is not used in this method but
* should be made available to overridden methods.
* @param {import('@appium/types').HTTPMethod} method - HTTP method of the route
* @param {string} url - url of the route
* @param {any} [body] - webdriver request body
* @param method - HTTP method of the route
* @param url - url of the route
* @param [body] - webdriver request body
*
* @returns {boolean} - whether the route should be avoided
* @returns whether the route should be avoided
*/
proxyRouteIsAvoided(sessionId, method, url, body) {
for (let avoidSchema of this.getProxyAvoidList(sessionId)) {
proxyRouteIsAvoided(sessionId: string, method: HTTPMethod, url: string, body?: any): boolean {
for (const avoidSchema of this.getProxyAvoidList(sessionId)) {
if (!_.isArray(avoidSchema) || avoidSchema.length !== 2) {
throw new Error('Proxy avoidance must be a list of pairs');
}
let [avoidMethod, avoidPathRegex] = avoidSchema;
const [avoidMethod, avoidPathRegex] = avoidSchema;
if (!_.includes(['GET', 'POST', 'DELETE'], avoidMethod)) {
throw new Error(`Unrecognized proxy avoidance method '${avoidMethod}'`);
}
if (!_.isRegExp(avoidPathRegex)) {
throw new Error('Proxy avoidance path must be a regular expression');
}
let normalizedUrl = url.replace(new RegExp(`^${_.escapeRegExp(this.basePath)}`), '');
const normalizedUrl = url.replace(new RegExp(`^${_.escapeRegExp(this.basePath)}`), '');
if (avoidMethod === method && avoidPathRegex.test(normalizedUrl)) {
return true;
}
@@ -415,7 +363,7 @@ class DriverCore {
*
* @param {Driver} driver
*/
addManagedDriver(driver) {
addManagedDriver(driver: Driver) {
this.managedDrivers.push(driver);
}
@@ -430,26 +378,3 @@ class DriverCore {
}
}
}
export {DriverCore};
/**
* @typedef {import('@appium/types').Driver} Driver
* @typedef {import('@appium/types').Constraints} Constraints
* @typedef {import('@appium/types').ServerArgs} ServerArgs
* @typedef {import('@appium/types').EventHistory} EventHistory
* @typedef {import('@appium/types').AppiumLogger} AppiumLogger
* @typedef {import('@appium/types').StringRecord} StringRecord
* @typedef {import('@appium/types').BaseDriverCapConstraints} BaseDriverCapConstraints
*/
/**
* @template {Constraints} C
* @template {StringRecord} [S=StringRecord]
* @typedef {import('@appium/types').Core<C, S>} Core
*/
/**
* @template {Constraints} C
* @typedef {import('@appium/types').DriverOpts<C>} DriverOpts
*/
@@ -9,7 +9,7 @@ import {errors} from '../protocol/errors';
export const MAX_SETTINGS_SIZE = 20 * 1024 * 1024; // 20 MB
/**
* @template {import('@appium/types').StringRecord} T
* @template {StringRecord} T
* @implements {IDeviceSettings<T>}
*/
export class DeviceSettings {
@@ -74,6 +74,10 @@ export class DeviceSettings {
export default DeviceSettings;
/**
* @template {import('@appium/types').StringRecord} [T=import('@appium/types').StringRecord]
* @typedef {import('@appium/types').StringRecord} StringRecord
*/
/**
* @template {StringRecord} [T=StringRecord]
* @typedef {import('@appium/types').IDeviceSettings<T>} IDeviceSettings
*/
+45 -28
View File
@@ -1,28 +1,29 @@
import {validateCaps, processCapabilities} from './capabilities';
import {DriverCore} from './core';
import {util} from '@appium/support';
import {
BASE_DESIRED_CAP_CONSTRAINTS,
type AppiumServer,
type BaseDriverCapConstraints,
type Capabilities,
type Constraints,
type DefaultCreateSessionResult,
type Driver,
type DriverCaps,
type DriverData,
type MultiSessionData,
type ServerArgs,
type StringRecord,
type W3CDriverCaps,
type InitialOpts,
type DefaultDeleteSessionResult,
type SingularSessionData,
} from '@appium/types';
import B from 'bluebird';
import _ from 'lodash';
import {fixCaps, isW3cCaps} from '../helpers/capabilities';
import {DELETE_SESSION_COMMAND, determineProtocol, errors} from '../protocol';
import {processCapabilities, validateCaps} from './capabilities';
import {DriverCore} from './core';
import helpers from './helpers';
import {
AppiumServer,
BaseDriverCapConstraints,
BASE_DESIRED_CAP_CONSTRAINTS,
Capabilities,
Constraints,
DefaultCreateSessionResult,
Driver,
DriverCaps,
DriverData,
DriverOpts,
MultiSessionData,
ServerArgs,
SingularSessionData,
StringRecord,
W3CDriverCaps,
} from '@appium/types';
const EVENT_SESSION_INIT = 'newSessionRequested';
const EVENT_SESSION_START = 'newSessionStarted';
@@ -31,26 +32,26 @@ const EVENT_SESSION_QUIT_DONE = 'quitSessionFinished';
const ON_UNEXPECTED_SHUTDOWN_EVENT = 'onUnexpectedShutdown';
export class BaseDriver<
C extends Constraints,
const C extends Constraints,
CArgs extends StringRecord = StringRecord,
Settings extends StringRecord = StringRecord,
CreateResult = DefaultCreateSessionResult<C>,
DeleteResult = DefaultDeleteSessionResult,
SessionData extends StringRecord = StringRecord
>
extends DriverCore<C, Settings>
implements Driver<C, CArgs>
implements Driver<C, CArgs, Settings, CreateResult, DeleteResult, SessionData>
{
cliArgs: CArgs & ServerArgs;
caps: DriverCaps<C>;
originalCaps: W3CDriverCaps<C>;
desiredCapConstraints: C;
opts: DriverOpts<C>;
server?: AppiumServer;
serverHost?: string;
serverPort?: number;
serverPath?: string;
constructor(opts: DriverOpts<C>, shouldValidateCaps = true) {
constructor(opts: InitialOpts, shouldValidateCaps = true) {
super(opts, shouldValidateCaps);
this.caps = {} as DriverCaps<C>;
@@ -63,7 +64,7 @@ export class BaseDriver<
*
* Subclasses _shouldn't_ need to use this. If you need to use this, please create
* an issue:
* @see https://github.com/appium/appium/issues/new
* @see {@link https://github.com/appium/appium/issues/new}
*/
protected get _desiredCapConstraints(): Readonly<BaseDriverCapConstraints & C> {
return Object.freeze(_.merge({}, BASE_DESIRED_CAP_CONSTRAINTS, this.desiredCapConstraints));
@@ -234,7 +235,7 @@ export class BaseDriver<
w3cCapabilities?: W3CDriverCaps<C>,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
driverData?: DriverData[]
): Promise<DefaultCreateSessionResult<C>> {
): Promise<CreateResult> {
if (this.sessionId !== null) {
throw new errors.SessionNotCreatedError(
'Cannot create a new session while one is in progress'
@@ -311,7 +312,7 @@ export class BaseDriver<
this.log.info(`Session created with session id: ${this.sessionId}`);
return [this.sessionId, caps];
return [this.sessionId, caps] as CreateResult;
}
async getSessions() {
const ret: MultiSessionData<C>[] = [];
@@ -330,7 +331,9 @@ export class BaseDriver<
* Returns capabilities for the session and event history (if applicable)
*/
async getSession() {
return this.caps.eventTimings ? {...this.caps, events: this.eventHistory} : this.caps;
return (
this.caps.eventTimings ? {...this.caps, events: this.eventHistory} : this.caps
) as SingularSessionData<C, SessionData>;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -380,6 +383,20 @@ export class BaseDriver<
return true;
}
async updateSettings(newSettings: Settings) {
if (!this.settings) {
this.log.errorAndThrow('Cannot update settings; settings object not found');
}
return await this.settings.update(newSettings);
}
async getSettings() {
if (!this.settings) {
this.log.errorAndThrow('Cannot get settings; settings object not found');
}
return this.settings.getSettings();
}
}
export * from './commands';
@@ -1,4 +1,5 @@
import {util} from '@appium/support';
import {Protocol} from '@appium/types';
// The default maximum length of a single log record
// containing http request/response body
@@ -12,7 +13,7 @@ const W3C_ELEMENT_KEY = util.W3C_WEB_ELEMENT_IDENTIFIER;
const PROTOCOLS = {
W3C: 'W3C',
MJSONWP: 'MJSONWP',
};
} as const satisfies Record<Protocol, Protocol>;
// Before Appium 2.0, this default value was '/wd/hub' by historical reasons.
const DEFAULT_BASE_PATH = '';
+1 -1
View File
@@ -15,7 +15,7 @@ export default BaseDriver;
// MJSONWP exports
export * from './protocol';
export {errorFromMJSONWPStatusCode as errorFromCode} from './protocol';
export {DEFAULT_BASE_PATH, PROTOCOLS} from './constants';
export {DEFAULT_BASE_PATH, PROTOCOLS, W3C_ELEMENT_KEY} from './constants';
// Express exports
export {STATIC_DIR} from './express/static';
@@ -320,6 +320,12 @@ class JWProxy {
return commandName;
}
/**
*
* @param {string} url
* @param {import('@appium/types').HTTPMethod} method
* @param {any?} body
*/
async proxyCommand(url, method, body = null) {
const commandName = this.requestToCommandName(url, method);
if (!commandName) {
@@ -330,6 +336,13 @@ class JWProxy {
return await this.protocolConverter.convertAndProxy(commandName, url, method, body);
}
/**
*
* @param {string} url
* @param {import('@appium/types').HTTPMethod} method
* @param {any?} body
* @returns {Promise<unknown>}
*/
async command(url, method, body = null) {
let response;
let resBodyObj;
+8 -1
View File
@@ -982,7 +982,13 @@ function isUnknownError(err) {
})
);
}
/**
* Type guard to check if an Error is of a specific type
* @template {Error} T
* @param {any} err
* @param {import('@appium/types').Class<T>} type
* @returns {err is T}
*/
function isErrorType(err, type) {
// `name` property is the constructor name
if (type.name === ProtocolError.name) {
@@ -1072,6 +1078,7 @@ function getResponseForW3CError(err) {
w3cLog.debug(`Bad parameters: ${err}`);
w3cErrorString = BadParametersError.error();
} else {
// @ts-expect-error unclear what the problem is here
w3cErrorString = err.error;
}
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/base-driver",
"version": "9.3.11",
"version": "9.3.15",
"description": "Base driver class for Appium drivers",
"keywords": [
"automation",
@@ -37,15 +37,15 @@
"!build/tsconfig.tsbuildinfo"
],
"scripts": {
"test": "npm run test:unit",
"test:e2e": "mocha -p --timeout 20s --slow 10s \"./test/e2e/**/*.spec.js\"",
"test": "run-p test:unit test:types",
"test:e2e": "mocha --timeout 20s --slow 10s \"./test/e2e/**/*.spec.js\"",
"test:smoke": "node ./index.js",
"test:unit": "mocha \"./test/unit/**/*.spec.js\"",
"test:types": "tsd"
},
"dependencies": {
"@appium/support": "^4.0.2",
"@appium/types": "^0.12.0",
"@appium/support": "^4.1.2",
"@appium/types": "^0.13.2",
"@colors/colors": "1.5.0",
"@types/async-lock": "1.4.0",
"@types/bluebird": "3.5.38",
@@ -4,8 +4,8 @@ import {BaseDriver} from '.../../..';
import {BaseDriverCapConstraints, ExternalDriver, Driver, DriverOpts} from '@appium/types';
expectAssignable<Driver<BaseDriverCapConstraints>>(
new BaseDriver({} as DriverOpts<BaseDriverCapConstraints>)
new BaseDriver<BaseDriverCapConstraints>({} as DriverOpts<BaseDriverCapConstraints>)
);
expectAssignable<ExternalDriver<BaseDriverCapConstraints>>(
new BaseDriver({} as DriverOpts<BaseDriverCapConstraints>)
new BaseDriver<BaseDriverCapConstraints>({} as DriverOpts<BaseDriverCapConstraints>)
);
@@ -36,18 +36,15 @@ describe('Desired Capabilities', function () {
it('should require platformName', async function () {
await d
.createSession({
alwaysMatch: {
'appium:deviceName': 'Delorean',
},
alwaysMatch: {},
firstMatch: [{}],
})
.should.be.rejectedWith(errors.SessionNotCreatedError, /platformName/);
});
it('should not care about cap order', async function () {
await d.createSession(null, null, {
await d.createSession({
alwaysMatch: {
'appium:deviceName': 'Delorean',
platformName: 'iOS',
},
firstMatch: [{}],
@@ -67,10 +64,9 @@ describe('Desired Capabilities', function () {
};
await d
.createSession(null, null, {
.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Delorean',
},
firstMatch: [{}],
})
@@ -90,7 +86,7 @@ describe('Desired Capabilities', function () {
});
await d
.createSession(null, null, {
.createSession({
alwaysMatch: {
'appium:necessary': 'yup',
},
@@ -100,28 +96,22 @@ describe('Desired Capabilities', function () {
});
it('should accept extra capabilities', async function () {
await d.createSession(
null,
null,
/** @type {import('@appium/types').W3CCapabilities<{'hold the':string}>} */ ({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Delorean',
'appium:extra': 'cheese',
'appium:hold the': 'sauce',
},
firstMatch: [{}],
})
).should.be.fulfilled;
await d.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:extra': 'cheese',
'appium:hold the': 'sauce',
},
firstMatch: [{}],
}).should.be.fulfilled;
});
it('should log the use of extra caps', async function () {
this.timeout(500);
await d.createSession(null, null, {
await d.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Delorean',
'appium:extra': 'cheese',
'appium:hold the': 'sauce',
},
@@ -133,11 +123,10 @@ describe('Desired Capabilities', function () {
it('should be sensitive to the case of caps', async function () {
await d
.createSession(null, null, {
.createSession({
alwaysMatch: {
// @ts-expect-error
platformname: 'iOS',
'appium:deviceName': 'Delorean',
},
firstMatch: [{}],
})
@@ -146,10 +135,9 @@ describe('Desired Capabilities', function () {
describe('boolean capabilities', function () {
it('should allow a string "false"', async function () {
await d.createSession(null, null, {
await d.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Delorean',
// @ts-expect-error
'appium:noReset': 'false',
},
@@ -162,10 +150,9 @@ describe('Desired Capabilities', function () {
});
it('should allow a string "true"', async function () {
await d.createSession(null, null, {
await d.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Delorean',
// @ts-expect-error
'appium:noReset': 'true',
},
@@ -178,10 +165,9 @@ describe('Desired Capabilities', function () {
});
it('should allow a string "true" in string capabilities', async function () {
await d.createSession(null, null, {
await d.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Delorean',
'appium:language': 'true',
},
firstMatch: [{}],
@@ -195,10 +181,9 @@ describe('Desired Capabilities', function () {
describe('number capabilities', function () {
it('should allow a string "1"', async function () {
await d.createSession(null, null, {
await d.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Delorean',
// @ts-expect-error
'appium:newCommandTimeout': '1',
},
@@ -211,10 +196,9 @@ describe('Desired Capabilities', function () {
});
it('should allow a string "1.1"', async function () {
await d.createSession(null, null, {
await d.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Delorean',
// @ts-expect-error
'appium:newCommandTimeout': '1.1',
},
@@ -227,10 +211,9 @@ describe('Desired Capabilities', function () {
});
it('should allow a string "1" in string capabilities', async function () {
await d.createSession(null, null, {
await d.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Delorean',
'appium:language': '1',
},
firstMatch: [{}],
@@ -244,11 +227,10 @@ describe('Desired Capabilities', function () {
it('should error if objects in caps', async function () {
await d
.createSession(null, null, {
.createSession({
alwaysMatch: {
// @ts-expect-error
platformName: {a: 'iOS'},
'appium:deviceName': 'Delorean',
},
firstMatch: [{}],
})
@@ -264,10 +246,9 @@ describe('Desired Capabilities', function () {
},
};
await d.createSession(null, null, {
await d.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Delorean',
'appium:lynx-version': 5,
},
firstMatch: [{}],
@@ -285,10 +266,9 @@ describe('Desired Capabilities', function () {
},
};
await d.createSession(null, null, {
await d.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Delorean',
'appium:lynx-version': 5,
},
firstMatch: [{}],
@@ -305,10 +285,9 @@ describe('Desired Capabilities', function () {
};
try {
await d.createSession(null, null, {
await d.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Dumb',
'appium:foo': null,
},
firstMatch: [{}],
@@ -318,10 +297,9 @@ describe('Desired Capabilities', function () {
}
await d
.createSession(null, null, {
.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Dumb',
'appium:foo': 1,
},
firstMatch: [{}],
@@ -329,10 +307,9 @@ describe('Desired Capabilities', function () {
.should.be.rejectedWith(/'foo' must be of type string/);
try {
await d.createSession(null, null, {
await d.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Dumb',
'appium:foo': undefined,
},
firstMatch: [{}],
@@ -342,10 +319,9 @@ describe('Desired Capabilities', function () {
}
try {
await d.createSession(null, null, {
await d.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Dumb',
'appium:foo': '',
},
firstMatch: [{}],
@@ -363,10 +339,9 @@ describe('Desired Capabilities', function () {
};
await d
.createSession(null, null, {
.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Dumb',
'appium:foo': null,
},
firstMatch: [{}],
@@ -374,10 +349,10 @@ describe('Desired Capabilities', function () {
.should.be.rejectedWith(/blank/);
await d
// @ts-expect-error `null` is not actually allowed here
.createSession(null, {
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Dumb',
'appium:foo': '',
},
firstMatch: [{}],
@@ -389,7 +364,6 @@ describe('Desired Capabilities', function () {
firstMatch: [
{
platformName: 'iOS',
'appium:deviceName': 'Dumb',
'appium:foo': {},
},
],
@@ -401,7 +375,6 @@ describe('Desired Capabilities', function () {
.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Dumb',
'appium:foo': [],
},
firstMatch: [{}],
@@ -412,7 +385,6 @@ describe('Desired Capabilities', function () {
.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Dumb',
'appium:foo': ' ',
},
firstMatch: [{}],
@@ -422,17 +394,15 @@ describe('Desired Capabilities', function () {
describe('w3c', function () {
it('should accept w3c capabilities', async function () {
const [sessionId, caps] = await d.createSession(null, null, {
const [sessionId, caps] = await d.createSession({
alwaysMatch: {
platformName: 'iOS',
'appium:deviceName': 'Delorean',
},
firstMatch: [{}],
});
sessionId.should.exist;
caps.should.eql({
platformName: 'iOS',
deviceName: 'Delorean',
});
});
@@ -442,7 +412,7 @@ describe('Desired Capabilities', function () {
await B.map(testValues, (val) =>
d
// @ts-expect-error
.createSession(null, null, val)
.createSession(val)
.should.be.rejectedWith(errors.SessionNotCreatedError)
);
});
+32
View File
@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.2.15](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.14...@appium/base-plugin@2.2.15) (2023-07-03)
**Note:** Version bump only for package @appium/base-plugin
## [2.2.14](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.13...@appium/base-plugin@2.2.14) (2023-06-29)
**Note:** Version bump only for package @appium/base-plugin
## [2.2.13](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.12...@appium/base-plugin@2.2.13) (2023-06-15)
**Note:** Version bump only for package @appium/base-plugin
## [2.2.12](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.11...@appium/base-plugin@2.2.12) (2023-06-14)
**Note:** Version bump only for package @appium/base-plugin
## [2.2.11](https://github.com/appium/appium/compare/@appium/base-plugin@2.2.10...@appium/base-plugin@2.2.11) (2023-06-14)
**Note:** Version bump only for package @appium/base-plugin
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/base-plugin",
"version": "2.2.11",
"version": "2.2.15",
"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.3.11",
"@appium/support": "^4.0.2"
"@appium/base-driver": "^9.3.15",
"@appium/support": "^4.1.2"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
+33
View File
@@ -3,6 +3,39 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.0.21](https://github.com/appium/appium/compare/@appium/doctor@2.0.20...@appium/doctor@2.0.21) (2023-07-03)
### Bug Fixes
* **doctor:** update dependency appium-adb to v9.11.7 ([fdd2ac0](https://github.com/appium/appium/commit/fdd2ac098d1b6e0d17b1429defa0123660d85ca9))
## [2.0.20](https://github.com/appium/appium/compare/@appium/doctor@2.0.19...@appium/doctor@2.0.20) (2023-06-29)
**Note:** Version bump only for package @appium/doctor
## [2.0.19](https://github.com/appium/appium/compare/@appium/doctor@2.0.18...@appium/doctor@2.0.19) (2023-06-15)
**Note:** Version bump only for package @appium/doctor
## [2.0.18](https://github.com/appium/appium/compare/@appium/doctor@2.0.17...@appium/doctor@2.0.18) (2023-06-14)
**Note:** Version bump only for package @appium/doctor
## [2.0.17](https://github.com/appium/appium/compare/@appium/doctor@2.0.16...@appium/doctor@2.0.17) (2023-06-14)
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/doctor",
"version": "2.0.17",
"version": "2.0.21",
"description": "Test environment for fitness to run Appium",
"keywords": [
"automation",
@@ -44,11 +44,11 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/support": "^4.0.2",
"@appium/support": "^4.1.2",
"@colors/colors": "1.5.0",
"@types/bluebird": "3.5.38",
"@types/teen_process": "2.0.0",
"appium-adb": "9.11.5",
"appium-adb": "9.11.7",
"bluebird": "3.7.2",
"inquirer": "8.2.5",
"lodash": "4.17.21",
+36
View File
@@ -3,6 +3,42 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.4.4](https://github.com/appium/appium/compare/@appium/docutils@0.4.3...@appium/docutils@0.4.4) (2023-07-03)
### Bug Fixes
* **support:** update dependency semver to v7.5.3 ([ed1856d](https://github.com/appium/appium/commit/ed1856d720c442842d5c3fe5f6caeccb8229b5f1))
## [0.4.3](https://github.com/appium/appium/compare/@appium/docutils@0.4.2...@appium/docutils@0.4.3) (2023-06-29)
### Bug Fixes
* **docutils:** docs versioning and update latest ([#18804](https://github.com/appium/appium/issues/18804)) ([52a755a](https://github.com/appium/appium/commit/52a755a9135e06ad676cc422e37b5cab019c5b85))
## [0.4.2](https://github.com/appium/appium/compare/@appium/docutils@0.4.1...@appium/docutils@0.4.2) (2023-06-15)
### Bug Fixes
* **docutils:** set mike version to major.minor by default ([#18770](https://github.com/appium/appium/issues/18770)) ([1a5b8cc](https://github.com/appium/appium/commit/1a5b8cca2d22b0be0150fe87be963973c4cc04e5))
## [0.4.1](https://github.com/appium/appium/compare/@appium/docutils@0.4.0...@appium/docutils@0.4.1) (2023-06-14)
### Bug Fixes
* **docutils:** fixes some weirdness with default behavior and the "implies" keyword ([#18751](https://github.com/appium/appium/issues/18751)) ([e5254b5](https://github.com/appium/appium/commit/e5254b5b4564450252fd3eb55b773c0d7c615316))
## [0.4.0](https://github.com/appium/appium/compare/@appium/docutils@0.3.13...@appium/docutils@0.4.0) (2023-06-14)
+2
View File
@@ -1,6 +1,8 @@
#!/usr/bin/env node
// @ts-check
'use strict';
require('source-map-support').install();
const {main} = require('../build/lib/cli');
const {getLogger} = require('../build/lib/logger');
+34 -22
View File
@@ -18,7 +18,7 @@ import {
NAME_PYTHON,
} from '../constants';
import {DocutilsError} from '../error';
import {findMkDocsYml, findPython, readPackageJson} from '../fs';
import {findMike, findMkDocsYml, findPython, readPackageJson} from '../fs';
import {getLogger} from '../logger';
import {argify, spawnBackgroundProcess, SpawnBackgroundProcessOpts, stopwatch} from '../util';
@@ -26,33 +26,29 @@ const log = getLogger('builder:deploy');
/**
* Runs `mike serve`
* @param pythonPath Path to Python 3 executable
* @param mikePath Path to `mike` executable
* @param args Extra args to `mike build`
* @param opts Extra options for `teen_process.Subprocess.start`
*/
async function doServe(
pythonPath: string,
mikePath: string,
args: string[] = [],
opts: SpawnBackgroundProcessOpts = {}
) {
const finalArgs = ['-m,', NAME_MIKE, 'serve', ...args];
return spawnBackgroundProcess(pythonPath, finalArgs, opts);
const finalArgs = ['serve', ...args];
return spawnBackgroundProcess(mikePath, finalArgs, opts);
}
/**
* Runs `mike build`
* @param pythonPath Path to Python 3 executable
* @param mikePath Path to `mike` executable
* @param args Extra args to `mike build`
* @param opts Extra options to `teen_process.exec`
*/
async function doDeploy(
pythonPath: string,
args: string[] = [],
opts: TeenProcessExecOptions = {}
) {
const finalArgs = ['-m', NAME_MIKE, 'deploy', ...args];
log.debug('Executing %s via: %s %O', NAME_MIKE, pythonPath, finalArgs);
return await exec(pythonPath, finalArgs, opts);
async function doDeploy(mikePath: string, args: string[] = [], opts: TeenProcessExecOptions = {}) {
const finalArgs = ['deploy', ...args];
log.debug('Executing %s via: %s %O', NAME_MIKE, mikePath, finalArgs);
return await exec(mikePath, finalArgs, opts);
}
/**
@@ -68,7 +64,14 @@ async function findDeployVersion(packageJsonPath?: string, cwd = process.cwd()):
'No "version" field found in package.json; please add one or specify a version to deploy'
);
}
return version;
// return MAJOR.MINOR as the version by default, if that is a thing we can extract, otherwise
// just return the version as is
const versionParts = version.split('.');
if (versionParts.length === 1) {
return version;
}
return `${versionParts[0]}.${versionParts[1]}`;
}
/**
@@ -125,17 +128,25 @@ export async function deploy({
port,
host,
};
const mikePath = await findMike();
if (!mikePath) {
throw new DocutilsError(
`Could not find ${NAME_MIKE} executable; please run "${NAME_BIN} init"`
);
}
if (serve) {
const mikeArgs = [
...argify(_.pickBy(mikeOpts, (value) => _.isNumber(value) || Boolean(value))),
version,
...argify(_.pickBy(mikeOpts, (value) => _.isNumber(value) || Boolean(value)))
];
if (alias) {
mikeArgs.push(alias);
mikeArgs.push('--update-aliases', version, alias);
} else {
mikeArgs.push(version);
}
stop(); // discard
// unsure about how SIGHUP is handled here
await doServe(pythonPath, mikeArgs, serveOpts);
await doServe(mikePath, mikeArgs, serveOpts);
} else {
log.info('Deploying into branch %s', branch);
const mikeArgs = [
@@ -145,12 +156,13 @@ export async function deploy({
(value, key) => _.includes(['port', 'host'], key) || (!_.isNumber(value) && !value)
)
),
version,
];
if (alias) {
mikeArgs.push(alias);
mikeArgs.push('--update-aliases', version, alias);
} else {
mikeArgs.push(version);
}
await doDeploy(pythonPath, mikeArgs, execOpts);
await doDeploy(mikePath, mikeArgs, execOpts);
log.success('Finished deployment into branch %s (%dms)', branch, stop());
}
+11 -9
View File
@@ -100,8 +100,10 @@ export function parseNav(nav: MkDocsYmlNav): ParsedNavData[] {
}
/**
* Finds all items within the list of parsed nav data which correpsond to the header. This is
* imperfect, as it's possible for the header string to appear in multiple places in the nav, but let's just ignore that until we can't.
* Finds all items within the list of parsed nav data which correpsond to the header.
*
* This is imperfect, as it's possible for the header string to appear in multiple places in the
* nav, but let's just ignore that until we can't.
* @param navData Some parsed nav data
* @param header Header name
*/
@@ -110,6 +112,8 @@ function filterHeaderItems(navData: ParsedNavData[], header: string) {
}
/**
* Given a root header keypath (like a prefix), a numeric offset, and some parsed nav data, compute
* a keypath
*
* @param rootHeaderKeypath Root keypath as determined by {@linkcode getRootHeaderKeypath}
* @param offset Numeric offset within the array of items for the header
@@ -136,16 +140,16 @@ function navDataDidChange(
newNavData: Array<Omit<ParsedNavData, 'name'>>,
navData: ParsedNavData[]
): boolean {
const diff = _.xorWith(
newNavData,
navData,
(a, b) => a.keypath === b.keypath && a.fileOrUrl === b.fileOrUrl
);
// the result should be the items from newNavData which either don't appear in
// navdata, or the items which do appear in navData but have a different fileOrUrl
const matchedKeypaths = _.intersectionBy(newNavData, navData, 'keypath');
const diff = _.xorBy(newNavData, matchedKeypaths, 'fileOrUrl');
return !_.isEmpty(diff);
}
/**
* Find the "root" keypath for a particular header
*
* @param headerItems Some subset of the nav data having keypaths corresponding to `header`
* @param header Header string
* @returns The keypath up to the header string, inclusive
@@ -167,7 +171,6 @@ function getRootHeaderKeypath(headerItems: ParsedNavData[], header: string) {
* by `dir`; if `all` is true, we just use the default header, because we will be returning a whole
* lot of headers).
*
*
* @param dir Abs path to directory containing markdown files generated by TypeDoc
* @param mkDocsDocsDir Configured `docs_dir` or via options
* @param navData Nav data parsed by {@linkcode parseNav}
@@ -202,7 +205,6 @@ async function getNavItemsForDir(
const offset = navHeaderItems.findIndex((item) => item.fileOrUrl === fileOrUrl);
const newOffset = offset >= 0 ? offset : navHeaderItems.length;
const data = navHeaderItems[offset];
log.warn(rootHeaderKeypath, newOffset, data);
const keypath = getKeypathForHeaderItem(rootHeaderKeypath, newOffset, data);
newNavHeaderItems.push({keypath, fileOrUrl});
}
+4 -3
View File
@@ -124,7 +124,7 @@ const opts = {
remote: {
alias: 'r',
describe: 'Remote to push to',
implies: ['deploy', 'push'],
implies: 'push',
group: BuildCommandGroup.Deploy,
type: 'string',
requiresArg: true,
@@ -133,7 +133,7 @@ const opts = {
},
prefix: {
describe: 'Subdirectory within <branch> to commit to',
implies: ['deploy', 'branch'],
implies: 'branch',
group: BuildCommandGroup.Deploy,
type: 'string',
nargs: 1,
@@ -168,9 +168,10 @@ const opts = {
},
rebase: {
describe: 'Rebase <branch> with remote before deploy',
implies: ['deploy', 'branch', 'remote'],
implies: 'deploy',
group: BuildCommandGroup.Deploy,
type: 'boolean',
defaultDescription: 'true',
},
serve: {
describe: 'Start development server',
+30
View File
@@ -14,6 +14,7 @@ import {JsonValue} from 'type-fest';
import {Application, TypeDocReader} from 'typedoc';
import YAML from 'yaml';
import {
NAME_MIKE,
NAME_MKDOCS_YML,
NAME_NPM,
NAME_PACKAGE_JSON,
@@ -24,6 +25,7 @@ import {
import {DocutilsError} from './error';
import {getLogger} from './logger';
import {MkDocsYml} from './model';
import { exec } from 'teen_process';
const log = getLogger('fs');
@@ -228,6 +230,34 @@ const whichPython3 = _.partial(cachedWhich, `${NAME_PYTHON}3`, {nothrow: true});
*/
const whichTypeDoc = _.partial(cachedWhich, NAME_TYPEDOC, {nothrow: true});
/**
* `mike` cannot be invoked via `python -m`, so we need to find the script.
*/
export const findMike = _.partial(async () => {
// see if it's in PATH
let mikePath = await cachedWhich(NAME_MIKE, {nothrow: true});
if (mikePath) {
return mikePath;
}
// if it isn't, it may be in a user dir
const pythonPath = await findPython();
if (!pythonPath) {
return;
}
try {
// the user dir can be found this way.
// usually it's something like ~/.local
const {stdout} = await exec(pythonPath, ['-m', 'site', '--user-base']);
if (stdout) {
mikePath = path.join(stdout.trim(), 'bin', 'mike');
if (await fs.isExecutable(mikePath)) {
return mikePath;
}
}
}
catch {}
});
/**
* Finds the `typedoc` executable.
*
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/docutils",
"version": "0.4.0",
"version": "0.4.4",
"description": "Documentation generation utilities for Appium and related projects",
"keywords": [
"automation",
@@ -49,7 +49,7 @@
"start": "node ./build/lib/cli/index.js"
},
"dependencies": {
"@appium/support": "^4.0.2",
"@appium/support": "^4.1.2",
"@appium/tsconfig": "^0.3.0",
"@appium/typedoc-plugin-appium": "^0.6.5",
"@sliphua/lilconfig-ts-loader": "3.2.2",
@@ -65,7 +65,7 @@
"log-symbols": "4.1.0",
"pkg-dir": "5.0.0",
"read-pkg": "5.2.0",
"semver": "7.5.1",
"semver": "7.5.3",
"source-map-support": "0.5.21",
"teen_process": "2.0.2",
"type-fest": "3.11.1",
+1 -1
View File
@@ -1,4 +1,4 @@
mkdocs==1.4.3
mkdocs-material==9.1.15
mkdocs-material==9.1.17
mkdocs-material-extensions==1.1.1
mike==1.1.2
+24
View File
@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.4.10](https://github.com/appium/appium/compare/@appium/driver-test-support@0.4.9...@appium/driver-test-support@0.4.10) (2023-07-03)
**Note:** Version bump only for package @appium/driver-test-support
## [0.4.9](https://github.com/appium/appium/compare/@appium/driver-test-support@0.4.8...@appium/driver-test-support@0.4.9) (2023-06-29)
**Note:** Version bump only for package @appium/driver-test-support
## [0.4.8](https://github.com/appium/appium/compare/@appium/driver-test-support@0.4.7...@appium/driver-test-support@0.4.8) (2023-06-15)
**Note:** Version bump only for package @appium/driver-test-support
## [0.4.7](https://github.com/appium/appium/compare/@appium/driver-test-support@0.4.6...@appium/driver-test-support@0.4.7) (2023-06-14)
+46 -18
View File
@@ -5,9 +5,10 @@ import B from 'bluebird';
import {TEST_HOST, getTestPort, createAppiumURL} from './helpers';
import chai from 'chai';
import sinon from 'sinon';
import { Agent } from 'node:http';
import {Agent} from 'node:http';
const should = chai.should();
const {expect} = chai;
/**
* Creates some helper functions for E2E tests to manage sessions.
@@ -150,7 +151,7 @@ export function driverE2ETestSuite(DriverClass, defaultCaps = {}) {
describe('session handling', function () {
it('should handle idempotency while creating sessions', async function () {
// workaround for https://github.com/node-fetch/node-fetch/issues/1735
const httpAgent = new Agent({ keepAlive: true });
const httpAgent = new Agent({keepAlive: true});
const sessionIds = [];
let times = 0;
@@ -179,7 +180,7 @@ export function driverE2ETestSuite(DriverClass, defaultCaps = {}) {
it('should handle idempotency while creating parallel sessions', async function () {
// workaround for https://github.com/node-fetch/node-fetch/issues/1735
const httpAgent = new Agent({ keepAlive: true });
const httpAgent = new Agent({keepAlive: true});
const reqs = [];
let times = 0;
@@ -400,22 +401,49 @@ export function driverE2ETestSuite(DriverClass, defaultCaps = {}) {
});
describe('event timings', function () {
it('should not add timings if not using opt-in cap', async function () {
const session = await startSession({capabilities: {alwaysMatch: defaultCaps}});
const res = await getSession(session.sessionId);
should.not.exist(res.events);
await endSession(session.sessionId);
/** @type {NewSessionResponse} */
let session;
/** @type {SingularSessionData} */
let res;
describe('when not provided the eventTimings cap', function () {
before(async function () {
session = await startSession({capabilities: {alwaysMatch: defaultCaps}});
res = await getSession(session.sessionId);
});
after(async function () {
if (session) {
await endSession(session.sessionId);
}
});
it('should not respond with events', function () {
expect(res.events).to.be.undefined;
});
});
it('should add start session timings', async function () {
const caps = {...defaultCaps, 'appium:eventTimings': true};
const session = await startSession({capabilities: {alwaysMatch: caps}});
const res = await getSession(session.sessionId);
should.exist(res.events);
should.exist(res.events?.newSessionRequested);
should.exist(res.events?.newSessionStarted);
res.events?.newSessionRequested[0].should.be.a('number');
res.events?.newSessionStarted[0].should.be.a('number');
await endSession(session.sessionId);
describe('when provided the eventTimings cap', function () {
before(async function () {
session = await startSession({
capabilities: {alwaysMatch: {...defaultCaps, 'appium:eventTimings': true}},
});
res = await getSession(session.sessionId);
});
after(async function () {
if (session) {
await endSession(session.sessionId);
}
});
it('should add a newSessionRequested event', function () {
expect(res.events?.newSessionRequested?.[0]).to.be.a('number');
});
it('should add a newSessionStarted event', function () {
expect(res.events?.newSessionRequested?.[0]).to.be.a('number');
});
});
});
});
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/driver-test-support",
"version": "0.4.7",
"version": "0.4.10",
"description": "Test utilities for Appium drivers",
"keywords": [
"automation",
@@ -41,7 +41,7 @@
},
"types": "./build/lib/index.d.ts",
"dependencies": {
"@appium/types": "^0.12.0",
"@appium/types": "^0.13.2",
"@types/lodash": "4.14.195",
"@types/stoppable": "1.1.1",
"axios": "1.4.0",
@@ -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.
## [8.0.4](https://github.com/appium/appium/compare/@appium/eslint-config-appium@8.0.3...@appium/eslint-config-appium@8.0.4) (2023-07-03)
### Bug Fixes
* **eslint-config-appium:** remove prototype assignment warning ([679865e](https://github.com/appium/appium/commit/679865ed2f1df59baef8c4d884b0a63a9222940e))
## [8.0.3](https://github.com/appium/appium/compare/@appium/eslint-config-appium@8.0.2...@appium/eslint-config-appium@8.0.3) (2023-04-03)
**Note:** Version bump only for package @appium/eslint-config-appium
-12
View File
@@ -91,18 +91,6 @@ module.exports = {
'require-atomic-updates': 0,
'no-prototype-builtins': 1,
'no-redeclare': 1,
'no-restricted-syntax': [
'warn',
{
selector: 'AssignmentExpression[left.object.property.name="prototype"]',
message: 'Avoid assignment to prototype; use class fields, methods or mixins instead.',
},
{
selector:
'CallExpression[callee.object.name="Object"][callee.property.name="assign"][arguments.0.property.name="prototype"]',
message: 'Avoid assignment to prototype; use class fields, methods or mixins instead.',
},
],
},
overrides: [
/**
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/eslint-config-appium",
"version": "8.0.3",
"version": "8.0.4",
"description": "Shared ESLint config for Appium projects",
"keywords": [
"eslint",
+20
View File
@@ -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.
## [5.2.6](https://github.com/appium/appium/compare/@appium/fake-driver@5.2.5...@appium/fake-driver@5.2.6) (2023-07-03)
### Bug Fixes
* **types:** separate the type of opts from initialOpts ([d6cca51](https://github.com/appium/appium/commit/d6cca5175c3e55d4670936c9d216cd3a6610d16b))
## [5.2.5](https://github.com/appium/appium/compare/@appium/fake-driver@5.2.4...@appium/fake-driver@5.2.5) (2023-06-15)
### Bug Fixes
* **fake-driver:** update definition of findElOrEls ([598b255](https://github.com/appium/appium/commit/598b255e8d4a2b41cca0ec0c02a54c46946eadb5))
* **types,fake-driver:** getLog doesn't necessarily return an array ([00ae162](https://github.com/appium/appium/commit/00ae1625d73305b8840d45a0dc98ac3cc628ac37))
* **types:** various fixes for reality ([81bc527](https://github.com/appium/appium/commit/81bc527be6aa54dd30a012156b5752b8b821ac0c))
## [5.2.4](https://github.com/appium/appium/compare/@appium/fake-driver@5.2.3...@appium/fake-driver@5.2.4) (2023-06-14)
+70 -46
View File
@@ -7,17 +7,82 @@ import {util} from '@appium/support';
import {mixin} from './mixin';
const {W3C_WEB_ELEMENT_IDENTIFIER} = util;
async function findElOrEls<Ctx = any>(
this: FakeDriver<any>,
strategy: string,
selector: string,
mult: true,
context?: Ctx
): Promise<Element[]>;
async function findElOrEls<Ctx = any>(
this: FakeDriver<any>,
strategy: string,
selector: string,
mult: false,
context?: Ctx
): Promise<Element>;
async function findElOrEls<Ctx = any>(
this: FakeDriver<any>,
strategy: string,
selector: string,
mult: boolean,
context?: Ctx
): Promise<Element | Element[]> {
const qMap = {
xpath: 'xpathQuery',
id: 'idQuery',
'accessibility id': 'idQuery',
'class name': 'classQuery',
'tag name': 'classQuery',
'css selector': 'cssQuery',
} as Record<string, keyof FakeDriver['appModel']>;
// TODO this error checking should probably be part of MJSONWP?
if (!_.includes(_.keys(qMap), strategy)) {
throw new errors.UnknownCommandError();
}
if (selector === 'badsel') {
throw new errors.InvalidSelectorError();
}
const els = this.appModel[qMap[strategy]](selector, context);
let retval: Element | Element[];
if (els.length) {
if (mult) {
const allEls: Element[] = [];
for (const el of els) {
allEls.push(this.wrapNewEl(el));
}
retval = allEls;
} else {
retval = this.wrapNewEl(els[0]);
}
} else if (mult) {
retval = [];
} else {
throw new errors.NoSuchElementError();
}
return retval;
}
interface FakeDriverFindMixin {
getExistingElementForNode(node: FakeElement): string | null;
wrapNewEl(obj: FakeElement): Element;
findElOrEls<Many extends boolean, Ctx = any>(
findElOrEls(
this: FakeDriver,
strategy: string,
selector: string,
many: Many,
context?: Ctx
): Promise<Many extends true ? Element[] : Element>;
mult: true,
context?: any
): Promise<Element[]>;
findElOrEls(
this: FakeDriver,
strategy: string,
selector: string,
mult: false,
context?: any
): Promise<Element>;
findElement(strategy: string, selector: string): Promise<Element>;
findElements(strategy: string, selector: string): Promise<Element[]>;
findElementFromElement(elementId: string, strategy: string, selector: string): Promise<Element>;
@@ -56,48 +121,7 @@ const FindMixin: FakeDriverFindMixin = {
return {ELEMENT: maxElId, [W3C_WEB_ELEMENT_IDENTIFIER]: maxElId};
},
async findElOrEls<Many extends boolean, Ctx = any>(
this: FakeDriver,
strategy: string,
selector: string,
many: Many,
context: Ctx
): Promise<Many extends true ? Element[] : Element> {
const qMap = {
xpath: 'xpathQuery',
id: 'idQuery',
'accessibility id': 'idQuery',
'class name': 'classQuery',
'tag name': 'classQuery',
'css selector': 'cssQuery',
} as Record<string, keyof FakeDriver['appModel']>;
// TODO this error checking should probably be part of MJSONWP?
if (!_.includes(_.keys(qMap), strategy)) {
throw new errors.UnknownCommandError();
}
if (selector === 'badsel') {
throw new errors.InvalidSelectorError();
}
const els = this.appModel[qMap[strategy]](selector, context);
let retval: Element | Element[];
if (els.length) {
if (many) {
const allEls: Element[] = [];
for (const el of els) {
allEls.push(this.wrapNewEl(el));
}
retval = allEls;
} else {
retval = this.wrapNewEl(els[0]);
}
} else if (many) {
retval = [];
} else {
throw new errors.NoSuchElementError();
}
return retval as Many extends true ? Element[] : Element;
},
findElOrEls,
/**
* This should override whatever's in ExternalDriver
+3 -2
View File
@@ -8,7 +8,7 @@ const ORIENTATIONS = new Set(['LANDSCAPE', 'PORTRAIT']);
interface FakeDriverGeneralMixin {
title(): Promise<string>;
keys(value: string | string[]): Promise<void>;
setGeoLocation(location: Location): Promise<void>;
setGeoLocation(location: Location): Promise<Location>;
getGeoLocation(): Promise<Location>;
getPageSource(): Promise<string>;
getOrientation(): Promise<string>;
@@ -22,7 +22,7 @@ interface FakeDriverGeneralMixin {
doubleClick(): Promise<void>;
execute(script: string, args: any[]): Promise<any>;
fakeAddition(a: number, b: number, c?: number): Promise<number>;
getLog(type: string): Promise<unknown[]>;
getLog(type: string): Promise<any>;
}
declare module '../driver' {
@@ -46,6 +46,7 @@ const GeneralMixin: FakeDriverGeneralMixin = {
// TODO test this adequately once WD bug is fixed
this.appModel.lat = location.latitude;
this.appModel.long = location.longitude;
return location;
},
async getGeoLocation(this: FakeDriver) {
+1 -1
View File
@@ -55,7 +55,7 @@ export class FakeDriver extends BaseDriver {
elMap;
constructor(
opts = /** @type {import('@appium/types').DriverOpts<FakeDriverConstraints>} */ ({}),
opts = /** @type {import('@appium/types').InitialOpts} */ ({}),
shouldValidateCaps = true
) {
super(opts, shouldValidateCaps);
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/fake-driver",
"version": "5.2.4",
"version": "5.2.6",
"description": "Mock driver used internally by Appium for testing. Ignore",
"keywords": [
"automation",
+32
View File
@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.1.19](https://github.com/appium/appium/compare/@appium/fake-plugin@3.1.18...@appium/fake-plugin@3.1.19) (2023-07-03)
**Note:** Version bump only for package @appium/fake-plugin
## [3.1.18](https://github.com/appium/appium/compare/@appium/fake-plugin@3.1.17...@appium/fake-plugin@3.1.18) (2023-06-29)
**Note:** Version bump only for package @appium/fake-plugin
## [3.1.17](https://github.com/appium/appium/compare/@appium/fake-plugin@3.1.16...@appium/fake-plugin@3.1.17) (2023-06-15)
**Note:** Version bump only for package @appium/fake-plugin
## [3.1.16](https://github.com/appium/appium/compare/@appium/fake-plugin@3.1.15...@appium/fake-plugin@3.1.16) (2023-06-14)
**Note:** Version bump only for package @appium/fake-plugin
## [3.1.15](https://github.com/appium/appium/compare/@appium/fake-plugin@3.1.14...@appium/fake-plugin@3.1.15) (2023-06-14)
**Note:** Version bump only for package @appium/fake-plugin
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/fake-plugin",
"version": "3.1.15",
"version": "3.1.19",
"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.11",
"@appium/support": "^4.0.2",
"@appium/base-plugin": "^2.2.15",
"@appium/support": "^4.1.2",
"@types/bluebird": "3.5.38",
"bluebird": "3.7.2",
"lodash": "4.17.21",
+24
View File
@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.3.18](https://github.com/appium/appium/compare/@appium/plugin-test-support@0.3.17...@appium/plugin-test-support@0.3.18) (2023-07-03)
**Note:** Version bump only for package @appium/plugin-test-support
## [0.3.17](https://github.com/appium/appium/compare/@appium/plugin-test-support@0.3.16...@appium/plugin-test-support@0.3.17) (2023-06-29)
**Note:** Version bump only for package @appium/plugin-test-support
## [0.3.16](https://github.com/appium/appium/compare/@appium/plugin-test-support@0.3.15...@appium/plugin-test-support@0.3.16) (2023-06-15)
**Note:** Version bump only for package @appium/plugin-test-support
## [0.3.15](https://github.com/appium/appium/compare/@appium/plugin-test-support@0.3.14...@appium/plugin-test-support@0.3.15) (2023-06-14)
**Note:** Version bump only for package @appium/plugin-test-support
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/plugin-test-support",
"version": "0.3.15",
"version": "0.3.18",
"description": "Testing utilities for Appium plugins",
"keywords": [
"automation",
@@ -41,7 +41,7 @@
"test:unit": "exit 0"
},
"dependencies": {
"@appium/types": "^0.12.0",
"@appium/types": "^0.13.2",
"get-port": "5.1.1",
"log-symbols": "4.1.0",
"source-map-support": "0.5.21",
+9
View File
@@ -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.1](https://github.com/appium/appium/compare/@appium/schema@0.3.0...@appium/schema@0.3.1) (2023-07-03)
### Bug Fixes
* **appium:** restrict address to ipv6/hostname ([#18824](https://github.com/appium/appium/issues/18824)) ([f09fbb6](https://github.com/appium/appium/commit/f09fbb64dce0e179a007f3a0ae9800e61fbe90eb)), closes [#18716](https://github.com/appium/appium/issues/18716)
## [0.3.0](https://github.com/appium/appium/compare/@appium/schema@0.2.6...@appium/schema@0.3.0) (2023-06-14)
+10 -1
View File
@@ -26,7 +26,16 @@ export const AppiumConfigJsonSchema = /** @type {const} */ ({
description: 'IPv4/IPv6 address or a hostname to listen on',
title: 'address config',
type: 'string',
// this should be anyOf [format: "hostname" or format: "ipv6"], but there seems to be a bug in json-schema-to-typescript preventing "ipv6" from converting to type "string"'
anyOf: [
{
type: 'string',
format: 'hostname',
},
{
type: 'string',
format: 'ipv6',
},
],
},
'allow-cors': {
description:
+11 -1
View File
@@ -20,7 +20,17 @@
"default": "0.0.0.0",
"description": "IPv4/IPv6 address or a hostname to listen on",
"title": "address config",
"type": "string"
"type": "string",
"anyOf": [
{
"type": "string",
"format": "hostname"
},
{
"type": "string",
"format": "ipv6"
}
]
},
"allow-cors": {
"description": "Whether the Appium server should allow web browser connections from any host",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/schema",
"version": "0.3.0",
"version": "0.3.1",
"description": "Appium Configuration Schema",
"keywords": [
"automation",
+35
View File
@@ -3,6 +3,41 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [4.1.2](https://github.com/appium/appium/compare/@appium/support@4.1.1...@appium/support@4.1.2) (2023-07-03)
### Bug Fixes
* **support:** update dependency semver to v7.5.3 ([ed1856d](https://github.com/appium/appium/commit/ed1856d720c442842d5c3fe5f6caeccb8229b5f1))
## [4.1.1](https://github.com/appium/appium/compare/@appium/support@4.1.0...@appium/support@4.1.1) (2023-06-29)
**Note:** Version bump only for package @appium/support
## [4.1.0](https://github.com/appium/appium/compare/@appium/support@4.0.3...@appium/support@4.1.0) (2023-06-15)
### Features
* **support:** export a bunch of types that weren't properly exported ([88293f8](https://github.com/appium/appium/commit/88293f803933ecf7d258b02afd08d636b310a24b))
## [4.0.3](https://github.com/appium/appium/compare/@appium/support@4.0.2...@appium/support@4.0.3) (2023-06-14)
### Bug Fixes
* **support:** Require the optional sharp dep properly from mjpeg module ([#18769](https://github.com/appium/appium/issues/18769)) ([c18eb03](https://github.com/appium/appium/commit/c18eb03261a4c0f73ec71417825a387da1c59991))
## [4.0.2](https://github.com/appium/appium/compare/@appium/support@4.0.1...@appium/support@4.0.2) (2023-06-14)
+1 -1
View File
@@ -3,7 +3,7 @@ let _sharp;
/**
* @returns {import('sharp')}
*/
function requireSharp() {
export function requireSharp() {
if (!_sharp) {
try {
_sharp = require('sharp');
@@ -57,3 +57,24 @@ export default {
env,
console,
};
export type {ConsoleOpts} from './console';
export type {ReadFn, WalkDirCallback} from './fs';
export type {
NetOptions,
DownloadOptions,
AuthCredentials,
NotHttpUploadOptions,
HttpUploadOptions,
} from './net';
export type {InstallPackageOpts, ExecOpts, NpmInstallReceipt} from './npm';
export type {Affixes, OpenedAffixes} from './tempdir';
export type {PluralizeOptions, EncodingOptions, LockFileOptions, NonEmptyString} from './util';
export type {
ExtractAllOptions,
ZipEntry,
ZipOptions,
ZipCompressionOptions,
ZipSourceOptions,
} from './zip';
export type {SecureValuePreprocessingRule} from './log-internal';
+2 -2
View File
@@ -1,7 +1,7 @@
import _ from 'lodash';
import log from './logger';
import B from 'bluebird';
import sharp from 'sharp';
import {requireSharp} from './image-util';
import {Writable} from 'stream';
import {requirePackage} from './node';
import axios from 'axios';
@@ -77,7 +77,7 @@ class MJpegStream extends Writable {
}
try {
return await sharp(lastChunk).png().toBuffer();
return await requireSharp()(lastChunk).png().toBuffer();
} catch (e) {
return null;
}
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/support",
"version": "4.0.2",
"version": "4.1.2",
"description": "Support libs used across appium packages",
"keywords": [
"automation",
@@ -42,7 +42,7 @@
},
"dependencies": {
"@appium/tsconfig": "^0.3.0",
"@appium/types": "^0.12.0",
"@appium/types": "^0.13.2",
"@colors/colors": "1.5.0",
"@types/archiver": "5.3.2",
"@types/base64-stream": "1.0.2",
@@ -59,7 +59,7 @@
"@types/shell-quote": "1.7.1",
"@types/supports-color": "8.1.1",
"@types/teen_process": "2.0.0",
"@types/uuid": "9.0.1",
"@types/uuid": "9.0.2",
"@types/which": "3.0.0",
"archiver": "5.3.1",
"axios": "1.4.0",
@@ -86,7 +86,7 @@
"read-pkg": "5.2.0",
"resolve-from": "5.0.0",
"sanitize-filename": "1.6.3",
"semver": "7.5.1",
"semver": "7.5.3",
"shell-quote": "1.8.1",
"source-map-support": "0.5.21",
"supports-color": "8.1.1",
+1 -1
View File
@@ -1,4 +1,4 @@
import AppiumSupport from '../../lib/index.js';
import AppiumSupport from '../../lib/';
let {system, tempDir, util} = AppiumSupport;
+1 -1
View File
@@ -1,5 +1,5 @@
import path from 'path';
import {plist, tempDir, fs} from '../../lib/index.js';
import {plist, tempDir, fs} from '../../lib';
const binaryPlistPath = path.join(__dirname, 'assets', 'sample_binary.plist');
const textPlistPath = path.join(__dirname, 'assets', 'sample_text.plist');
+1 -1
View File
@@ -1,4 +1,4 @@
import {system} from '../../lib/index.js';
import {system} from '../../lib';
import os from 'os';
import {createSandbox} from 'sinon';
import * as teen_process from 'teen_process';
+1 -1
View File
@@ -1,4 +1,4 @@
import {tempDir, fs} from '../../lib/index.js';
import {tempDir, fs} from '../../lib';
describe('tempdir', function () {
afterEach(function () {
+32
View File
@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.0.20](https://github.com/appium/appium/compare/@appium/test-support@3.0.19...@appium/test-support@3.0.20) (2023-07-03)
**Note:** Version bump only for package @appium/test-support
## [3.0.19](https://github.com/appium/appium/compare/@appium/test-support@3.0.18...@appium/test-support@3.0.19) (2023-06-29)
**Note:** Version bump only for package @appium/test-support
## [3.0.18](https://github.com/appium/appium/compare/@appium/test-support@3.0.17...@appium/test-support@3.0.18) (2023-06-15)
**Note:** Version bump only for package @appium/test-support
## [3.0.17](https://github.com/appium/appium/compare/@appium/test-support@3.0.16...@appium/test-support@3.0.17) (2023-06-14)
**Note:** Version bump only for package @appium/test-support
## [3.0.16](https://github.com/appium/appium/compare/@appium/test-support@3.0.15...@appium/test-support@3.0.16) (2023-06-14)
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/test-support",
"version": "3.0.16",
"version": "3.0.20",
"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.0.2",
"@appium/support": "^4.1.2",
"@colors/colors": "1.5.0",
"bluebird": "3.7.2",
"lodash": "4.17.21",
+1 -1
View File
@@ -71,7 +71,7 @@ This packages uses snapshot tests to assert the generated markdown is correct.
To update the snapshots, execute:
```bash
UPDATE_SNAPSHOT=1 npm test
UPDATE_SNAPSHOT=1 npm run test:e2e
```
This will (likely) modify the snapshots in your working copy, so you will then need to commit them.
@@ -5,38 +5,6 @@ exports[`@appium/typedoc-plugin-appium theme command output should generate expe
## Commands
### \`getSettings\`
\`GET\` **\`/session/:sessionId/appium/settings\`**
Get the current settings for the session
<!-- comment source: method-signature -->
#### Response
\`StringRecord\`<\`any\`\\\\>
The settings object
### \`updateSettings\`
\`POST\` **\`/session/:sessionId/appium/settings\`**
Get the current settings for the session
<!-- comment source: method-signature -->
##### Required Parameters
- \`settings\`
#### Response
\`StringRecord\`<\`any\`\\\\>
The settings object
### \`createSession\`
\`POST\` **\`/session\`**
@@ -62,7 +30,7 @@ the latter.
#### Response
\`DefaultCreateSessionResult\`<\`C\`\\\\>
\`CreateResult\`
The capabilities object representing the created session
@@ -76,7 +44,7 @@ Returns capabilities for the session and event history (if applicable)
#### Response
\`DriverCaps\`<\`C\`\\\\>
\`SingularSessionData\`<\`C\`, \`SessionData\`\\\\>
A session data object
@@ -90,7 +58,7 @@ Returns capabilities for the session and event history (if applicable)
#### Response
\`DriverCaps\`<\`C\`\\\\>
\`SingularSessionData\`<\`C\`, \`SessionData\`\\\\>
A session data object
@@ -264,7 +232,7 @@ Get the log for a given log type.
#### Response
\`unknown\`[]
\`any\`
### \`getLog\`
@@ -282,7 +250,7 @@ Get the log for a given log type.
#### Response
\`unknown\`[]
\`any\`
### \`getLogEvents\`
@@ -360,6 +328,36 @@ Get data for all sessions running on an Appium server
A list of session data objects
### \`getSettings\`
\`GET\` **\`/session/:sessionId/appium/settings\`**
Update the session's settings dictionary with a new settings object
<!-- comment source: builtin-interface -->
#### Response
\`\`null\`\`
### \`updateSettings\`
\`POST\` **\`/session/:sessionId/appium/settings\`**
Update the session's settings dictionary with a new settings object
<!-- comment source: builtin-interface -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| \`settings\` | \`Settings\` | A key-value map of setting names to values. Settings not named in the map will not have their value adjusted. |
#### Response
\`\`null\`\`
### \`getStatus\`
\`GET\` **\`/status\`**
@@ -594,39 +592,7 @@ Get the driver args that were sent in via the CLI
#### Response
\`StringRecord\`<\`any\`\\\\> & \`ServerArgs\`
### \`getSettings\`
\`GET\` **\`/session/:sessionId/appium/settings\`**
Get the current settings for the session
<!-- comment source: method-signature -->
#### Response
\`StringRecord\`<\`any\`\\\\>
The settings object
### \`updateSettings\`
\`POST\` **\`/session/:sessionId/appium/settings\`**
Get the current settings for the session
<!-- comment source: method-signature -->
##### Required Parameters
- \`settings\`
#### Response
\`StringRecord\`<\`any\`\\\\>
The settings object
\`StringRecord\` & \`ServerArgs\`
### \`createSession\`
@@ -664,7 +630,7 @@ Returns capabilities for the session and event history (if applicable)
#### Response
\`DriverCaps\`<{ \`app\`: { \`isString\`: \`\`true\`\` = true; \`presence\`: \`\`true\`\` = true } ; \`uniqueApp\`: { \`isBoolean\`: \`\`true\`\` = true } }\\\\>
\`SingularSessionData\`<{ \`app\`: { \`isString\`: \`\`true\`\` = true; \`presence\`: \`\`true\`\` = true } ; \`uniqueApp\`: { \`isBoolean\`: \`\`true\`\` = true } }, \`StringRecord\`\\\\>
A session data object
@@ -678,7 +644,7 @@ Returns capabilities for the session and event history (if applicable)
#### Response
\`DriverCaps\`<{ \`app\`: { \`isString\`: \`\`true\`\` = true; \`presence\`: \`\`true\`\` = true } ; \`uniqueApp\`: { \`isBoolean\`: \`\`true\`\` = true } }\\\\>
\`SingularSessionData\`<{ \`app\`: { \`isString\`: \`\`true\`\` = true; \`presence\`: \`\`true\`\` = true } ; \`uniqueApp\`: { \`isBoolean\`: \`\`true\`\` = true } }, \`StringRecord\`\\\\>
A session data object
@@ -852,7 +818,7 @@ Get the log for a given log type.
#### Response
\`unknown\`[]
\`any\`
### \`getLog\`
@@ -870,7 +836,7 @@ Get the log for a given log type.
#### Response
\`unknown\`[]
\`any\`
### \`getLogEvents\`
@@ -948,6 +914,36 @@ Get data for all sessions running on an Appium server
A list of session data objects
### \`getSettings\`
\`GET\` **\`/session/:sessionId/appium/settings\`**
Update the session's settings dictionary with a new settings object
<!-- comment source: builtin-interface -->
#### Response
\`\`null\`\`
### \`updateSettings\`
\`POST\` **\`/session/:sessionId/appium/settings\`**
Update the session's settings dictionary with a new settings object
<!-- comment source: builtin-interface -->
#### Parameters
| Name | Type | Description |
| :------ | :------ | :------ |
| \`settings\` | \`StringRecord\` | A key-value map of setting names to values. Settings not named in the map will not have their value adjusted. |
#### Response
\`\`null\`\`
### \`getStatus\`
\`GET\` **\`/status\`**
+41
View File
@@ -3,6 +3,47 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.13.2](https://github.com/appium/appium/compare/@appium/types@0.13.1...@appium/types@0.13.2) (2023-07-03)
### Bug Fixes
* **appium:** restrict address to ipv6/hostname ([#18824](https://github.com/appium/appium/issues/18824)) ([f09fbb6](https://github.com/appium/appium/commit/f09fbb64dce0e179a007f3a0ae9800e61fbe90eb)), closes [#18716](https://github.com/appium/appium/issues/18716)
* **types,base-driver:** remove deviceName from base constraints ([01061b2](https://github.com/appium/appium/commit/01061b291981333bdec59adfbea60f0cef3d69c1))
* **types:** ensure return type of deleteSession can always be void ([ee9b2a3](https://github.com/appium/appium/commit/ee9b2a30dee4a24b351375862883986e6d4e618c))
* **types:** fix signature of updateSettings ([24e7aec](https://github.com/appium/appium/commit/24e7aeca7dcab69e84e797e9e3168492d0e70e83))
* **types:** separate the type of opts from initialOpts ([d6cca51](https://github.com/appium/appium/commit/d6cca5175c3e55d4670936c9d216cd3a6610d16b))
* **types:** update some more types to reflect reality ([62f4244](https://github.com/appium/appium/commit/62f4244753b450eb0c9b96483a8b04a40ef289d2))
## [0.13.1](https://github.com/appium/appium/compare/@appium/types@0.13.0...@appium/types@0.13.1) (2023-06-29)
**Note:** Version bump only for package @appium/types
## [0.13.0](https://github.com/appium/appium/compare/@appium/types@0.12.0...@appium/types@0.13.0) (2023-06-15)
### ⚠ BREAKING CHANGES
* **types:** This changes the def of `findElOrEls` and `findElOrElsWithProcessing` in `ExternalDriver` in a breaking manner.
So conditional types don't work like how I was using them. They work in capital-T-types (`type`), but they don't work as return values. Instead, what we should have is an overload. in this case, the function can be called one of two ways, and it returns a different thing depending on those values. _unfortunately_ this is a little hinky to implement, given that overloads are unsupported in _object literals_. they are supported in function statements or expressions, and they are supported in class definitions, but not object literals. you'll see what needs to happen to make this work in `FakeDriver` and `BaseDriver` in subsequent changesets; essentially the function must be defined outside of the object literal and then stuffed in there.
The other change here changes an `object` type (which does not allow arbitrary properties) to a `StringRecord` type within the type which converts `Constraints` to `Capabilities`. This affects caps for some drivers such as `chromedriverArgs` in `appium-android-driver`; anywhere where the constraint has `isObject: true`.
### Bug Fixes
* **types,fake-driver:** getLog doesn't necessarily return an array ([00ae162](https://github.com/appium/appium/commit/00ae1625d73305b8840d45a0dc98ac3cc628ac37))
* **types:** use overload instead of broken conditional type in findElOrEls ([63a5c22](https://github.com/appium/appium/commit/63a5c22127ab22acfde8d36e9b96bdd35614fe17))
* **types:** various fixes for reality ([81bc527](https://github.com/appium/appium/commit/81bc527be6aa54dd30a012156b5752b8b821ac0c))
## [0.12.0](https://github.com/appium/appium/compare/@appium/types@0.11.1...@appium/types@0.12.0) (2023-06-14)
+3 -1
View File
@@ -8,7 +8,9 @@
/**
* IPv4/IPv6 address or a hostname to listen on
*/
export type AddressConfig = string;
export type AddressConfig = AddressConfig1 & AddressConfig2;
export type AddressConfig1 = string;
export type AddressConfig2 = string;
/**
* Whether the Appium server should allow web browser connections from any host
*/
+1 -1
View File
@@ -50,7 +50,7 @@ export type ConstraintToCapKind<C extends Constraint> = C['isString'] extends tr
: C['isArray'] extends true
? string[]
: C['isObject'] extends true
? object
? StringRecord
: unknown;
/**
+6 -6
View File
@@ -30,16 +30,16 @@ export interface PayloadParams {
* }
* ```
*/
export type MethodMap<T extends Plugin | Driver<any>> = T extends Plugin
export type MethodMap<T extends Plugin | Driver> = T extends Plugin
? Readonly<PluginMethodMap<T>>
: T extends Driver<any>
: T extends Driver
? Readonly<DriverMethodMap<T>>
: never;
/**
* A {@linkcode MethodMap} for a {@linkcode Driver}.
*/
export interface DriverMethodMap<T extends Driver<any>> {
export interface DriverMethodMap<T extends Driver> {
[key: string]: {
GET?: DriverMethodDef<T>;
POST?: DriverMethodDef<T>;
@@ -118,7 +118,7 @@ export interface BaseExecuteMethodDef {
/**
* A definition of an execute method in a {@linkcode Driver}.
*/
export interface DriverExecuteMethodDef<T extends Driver<any>> extends BaseExecuteMethodDef {
export interface DriverExecuteMethodDef<T extends Driver> extends BaseExecuteMethodDef {
command: keyof ConditionalPick<T, DriverCommand>;
}
@@ -132,8 +132,8 @@ export interface PluginExecuteMethodDef<T extends Plugin> extends BaseExecuteMet
/**
* Definition of an execute method (which overloads the behavior of the `execute` command) in a {@linkcode Driver} or {@linkcode Plugin}.
*/
export type ExecuteMethodMap<T extends Plugin | Driver<any>> = T extends Plugin
export type ExecuteMethodMap<T extends Plugin | Driver> = T extends Plugin
? Readonly<StringRecord<PluginExecuteMethodDef<T>>>
: T extends Driver<any>
: T extends Driver
? Readonly<StringRecord<DriverExecuteMethodDef<T>>>
: never;
+1 -4
View File
@@ -1,4 +1,4 @@
import {Constraints} from './driver';
import type {Constraints} from './driver';
export const BASE_DESIRED_CAP_CONSTRAINTS = {
platformName: {
@@ -8,9 +8,6 @@ export const BASE_DESIRED_CAP_CONSTRAINTS = {
app: {
isString: true,
},
deviceName: {
isString: true,
},
platformVersion: {
isString: true,
},
+79 -102
View File
@@ -1,13 +1,13 @@
import type {EventEmitter} from 'events';
import {Entries} from 'type-fest';
import {ActionSequence} from './action';
import {Capabilities, DriverCaps, W3CCapabilities, W3CDriverCaps} from './capabilities';
import {ExecuteMethodMap, MethodMap} from './command';
import {ServerArgs} from './config';
import {HTTPHeaders, HTTPMethod} from './http';
import {AppiumLogger} from './logger';
import {AppiumServer, UpdateServerCallback} from './server';
import {Class, StringRecord, Element} from './util';
import type {EventEmitter} from 'node:events';
import type {Merge} from 'type-fest';
import type {ActionSequence} from './action';
import type {Capabilities, DriverCaps, W3CCapabilities, W3CDriverCaps} from './capabilities';
import type {ExecuteMethodMap, MethodMap} from './command';
import type {ServerArgs} from './config';
import type {HTTPHeaders, HTTPMethod} from './http';
import type {AppiumLogger} from './logger';
import type {AppiumServer, UpdateServerCallback} from './server';
import type {Class, Element, StringRecord} from './util';
/**
* Interface implemented by the `DeviceSettings` class in `@appium/base-driver`
@@ -291,15 +291,11 @@ export interface IFindCommands {
*
* @returns A single element or list of elements
*/
findElOrEls<Mult extends boolean, Ctx = any>(
strategy: string,
selector: string,
mult: Mult,
context?: Ctx
): Promise<Mult extends true ? Element[] : Element>;
findElOrEls(strategy: string, selector: string, mult: true, context?: any): Promise<Element[]>;
findElOrEls(strategy: string, selector: string, mult: false, context?: any): Promise<Element>;
/**
* This is a wrapper for {@linkcode IFindCommands.findElOrEls} that validates locator strategies
* This is a wrapper for {@linkcode findElOrEls} that validates locator strategies
* and implements the `appium:printPageSourceOnFindFailure` capability
*
* @param strategy - the locator strategy
@@ -309,12 +305,18 @@ export interface IFindCommands {
*
* @returns A single element or list of elements
*/
findElOrElsWithProcessing<Mult extends boolean, Ctx = any>(
findElOrElsWithProcessing(
strategy: string,
selector: string,
mult: Mult,
context?: Ctx
): Promise<Mult extends true ? Element[] : Element>;
mult: true,
context?: any
): Promise<Element[]>;
findElOrElsWithProcessing(
strategy: string,
selector: string,
mult: false,
context?: any
): Promise<Element>;
/**
* Get the current page/app source as HTML/XML
@@ -341,7 +343,7 @@ export interface ILogCommands {
*
* @param logType - Name/key of log type as defined in {@linkcode ILogCommands.supportedLogTypes}.
*/
getLog(logType: string): Promise<unknown[]>;
getLog(logType: string): Promise<any>;
}
/**
@@ -366,17 +368,17 @@ export interface LogDef {
*
* This implementation *should* drain, truncate or otherwise reset the log buffer.
*/
getter: (driver: any) => Promise<unknown[]> | unknown[];
getter: (driver: any) => Promise<unknown> | unknown;
}
export interface ISettingsCommands<T extends StringRecord = StringRecord> {
export interface ISettingsCommands<T extends object = object> {
/**
* Update the session's settings dictionary with a new settings object
*
* @param settings - A key-value map of setting names to values. Settings not named in the map
* will not have their value adjusted.
*/
updateSettings: (settings: StringRecord) => Promise<void>;
updateSettings: (settings: T) => Promise<void>;
/**
* Get the current settings for the session
@@ -439,7 +441,7 @@ export interface ISessionHandler<
* @param sessionId - the id of the session that is to be deleted
* @param driverData - the driver data for other currently-running sessions
*/
deleteSession(sessionId?: string, driverData?: DriverData[]): Promise<DeleteResult>;
deleteSession(sessionId?: string, driverData?: DriverData[]): Promise<DeleteResult | void>;
/**
* Get data for all sessions running on an Appium server
@@ -476,9 +478,9 @@ export interface Constraint {
/**
* A collection of constraints describing the allowed capabilities for a driver.
*/
export interface Constraints {
[name: string]: Constraint;
}
export type Constraints = {
readonly [name: string]: Constraint;
};
export interface DriverHelpers {
configureApp: (
@@ -524,36 +526,7 @@ export interface Cookie {
sameSite?: 'Lax' | 'Strict';
}
// Appium W3C WebDriver Extension
export interface StartScreenRecordOptions {
remotePath?: string;
username?: string;
password?: string;
method?: string;
forceRestart?: boolean;
timeLimit?: string;
videoType?: string;
videoQuality?: string;
videoFps?: string;
videoScale?: string;
bitRate?: string;
videoSize?: string;
bugReport?: string;
}
export interface StopScreenRecordOptions {
remotePath?: string;
user?: string;
pass?: string;
method?: string;
headers?: Record<string, string>;
fileFieldName?: string;
formFields: Record<string, string> | Entries<Record<string, string>>;
}
// JSONWP
export type Size = Pick<Rect, 'width' | 'height'>;
export type Position = Pick<Rect, 'x' | 'y'>;
@@ -595,6 +568,8 @@ export interface EventHistoryCommand {
endTime: number;
}
export type Protocol = 'MJSONWP' | 'W3C';
/**
* Methods and properties which both `AppiumDriver` and `BaseDriver` inherit.
*
@@ -604,8 +579,8 @@ export interface Core<C extends Constraints, Settings extends StringRecord = Str
shouldValidateCaps: boolean;
sessionId: string | null;
opts: DriverOpts<C>;
initialOpts: Partial<DriverOpts<C>>;
protocol?: string;
initialOpts: InitialOpts;
protocol?: Protocol;
helpers: DriverHelpers;
basePath: string;
relaxedSecurityEnabled: boolean;
@@ -663,12 +638,12 @@ export interface Core<C extends Constraints, Settings extends StringRecord = Str
proxyActive(sessionId?: string): boolean;
getProxyAvoidList(sessionId?: string): RouteMatcher[];
canProxy(sessionId?: string): boolean;
proxyRouteIsAvoided(sessionId: string, method: string, url: string): boolean;
proxyRouteIsAvoided(sessionId: string, method: string, url: string, body?: any): boolean;
addManagedDriver(driver: Driver): void;
getManagedDrivers(): Driver<Constraints>[];
clearNewCommandTimeout(): Promise<void>;
logEvent(eventName: string): void;
driverForSession(sessionId: string): Core<C> | null;
driverForSession(sessionId: string): Core<Constraints> | null;
}
/**
@@ -789,8 +764,15 @@ export interface Driver<
* External drivers must subclass `BaseDriver`, and can implement any of these methods.
* None of these are implemented within Appium itself.
*/
export interface ExternalDriver<C extends Constraints = Constraints, Ctx = string>
extends Driver<C> {
export interface ExternalDriver<
C extends Constraints = Constraints,
Ctx = string,
CArgs extends StringRecord = StringRecord,
Settings extends StringRecord = StringRecord,
CreateResult = DefaultCreateSessionResult<C>,
DeleteResult = DefaultDeleteSessionResult,
SessionData extends StringRecord = StringRecord
> extends Driver<C, CArgs, Settings, CreateResult, DeleteResult, SessionData> {
// WebDriver spec commands
/**
@@ -1247,7 +1229,6 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @returns The list of types
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
getPerformanceDataTypes?(): Promise<string[]>;
@@ -1262,13 +1243,12 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @returns A list of performance data strings
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
getPerformanceData?(
packageName: string,
dataType: string,
dataReadTimeout?: number
): Promise<string[]>;
): Promise<any>;
/**
* Press a device hardware key by its code for the default duration
@@ -1278,7 +1258,6 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param flags - the code denoting the combination of extra flags
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
pressKeyCode?(keycode: number, metastate?: number, flags?: number): Promise<void>;
@@ -1290,7 +1269,7 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param flags - the code denoting the combination of extra flags
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*
*/
longPressKeyCode?(keycode: number, metastate?: number, flags?: number): Promise<void>;
@@ -1300,7 +1279,6 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param fingerprintId - the numeric ID of the fingerprint to use
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
fingerprint?(fingerprintId: number): Promise<void>;
@@ -1311,7 +1289,6 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param message - the SMS text
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
sendSMS?(phoneNumber: string, message: string): Promise<void>;
@@ -1323,7 +1300,6 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param action - the action to take in response (accept, reject, etc...)
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
gsmCall?(phoneNumber: string, action: string): Promise<void>;
@@ -1333,9 +1309,8 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param singalStrength - the strength in a driver-appropriate string
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
gsmSignal?(signalStrength: string): Promise<void>;
gsmSignal?(signalStrength: string | number): Promise<void>;
/**
* Do something with GSM voice (unclear; this should not be implemented anywhere)
@@ -1353,7 +1328,6 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param percent - how full the battery should become
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
powerCapacity?(percent: number): Promise<void>;
@@ -1363,7 +1337,6 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param state - whether the device is connected to power or not
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
powerAC?(state: string): Promise<void>;
@@ -1373,7 +1346,6 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param netspeed - the speed as a string, like '3G'
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
networkSpeed?(netspeed: string): Promise<void>;
@@ -1384,9 +1356,8 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param metastate - the combination of meta startUnexpectedShutdown
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
keyevent?(keycode: string, metastate?: string): Promise<void>;
keyevent?(keycode: string | number, metastate?: string | number): Promise<void>;
/**
* Construct a rotation gesture? Unclear what this command does and it does not appear to be used
@@ -1452,8 +1423,10 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
*
* @param appId - the package or bundle ID of the application
* @param options - driver-specific launch options
*
* @returns `true` if successful
*/
removeApp?(appId: string, options?: unknown): Promise<void>;
removeApp?(appId: string, options?: unknown): Promise<boolean>;
/**
* Quit / terminate / stop a running application
@@ -1461,7 +1434,7 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param appId - the package or bundle ID of the application
* @param options - driver-specific launch options
*/
terminateApp?(appId: string, options?: unknown): Promise<void>;
terminateApp?(appId: string, options?: unknown): Promise<boolean>;
/**
* Determine whether an app is installed
@@ -1488,8 +1461,15 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param key - the text of a key to use to hide the keyboard
* @param keyCode - a key code to trigger to hide the keyboard
* @param keyName - the name of a key to use to hide the keyboard
*
* @returns Whether the keyboard was successfully hidden. May never return `false` on some platforms
*/
hideKeyboard?(strategy?: string, key?: string, keyCode?: string, keyName?: string): Promise<void>;
hideKeyboard?(
strategy?: string,
key?: string,
keyCode?: string,
keyName?: string
): Promise<boolean>;
/**
* Determine whether the keyboard is shown
@@ -1600,9 +1580,8 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @returns An array of information objects of driver-specific shape
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
getSystemBars?(): Promise<unknown[]>;
getSystemBars?(): Promise<unknown>;
/**
* Get the display's pixel density
@@ -1665,7 +1644,6 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @returns The name of the active engine
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
getActiveIMEEngine?(): Promise<string>;
@@ -1675,7 +1653,6 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @returns True if the IME is activated
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
isIMEActivated?(): Promise<boolean>;
@@ -1683,7 +1660,6 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* Deactivate an IME engine
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
deactivateIMEEngine?(): Promise<void>;
@@ -1693,7 +1669,6 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param engine - the name of the engine
*
* @deprecated
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
activateIMEEngine?(engine: string): Promise<void>;
@@ -1756,9 +1731,8 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param y - the y coordinate
*
* @deprecated Use the Actions API instead
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
touchDown?(x: number, y: number): Promise<void>;
touchDown?(element: string, x: number, y: number): Promise<void>;
/**
* Perform a touch up event at the location specified
@@ -1767,9 +1741,8 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param y - the y coordinate
*
* @deprecated Use the Actions API instead
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
touchUp?(x: number, y: number): Promise<void>;
touchUp?(element: string, x: number, y: number): Promise<void>;
/**
* Perform a touch move event at the location specified
@@ -1778,9 +1751,8 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param y - the y coordinate
*
* @deprecated Use the Actions API instead
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
touchMove?(x: number, y: number): Promise<void>;
touchMove?(element: string, x: number, y: number): Promise<void>;
/**
* Perform a long touch down event at the location specified
@@ -1788,9 +1760,8 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @param elementId - the id of the element to long touch
*
* @deprecated Use the Actions API instead
* @privateRemarks Not implemented in `appium-xcuitest-driver`
*/
touchLongClick?(elementId: string): Promise<void>;
touchLongClick?(element: string, x: number, y: number, duration: number): Promise<void>;
/**
* Perform a flick event at the location specified
@@ -1825,8 +1796,9 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* Set the virtual geographical location of a device
*
* @param location - the location including latitude and longitude
* @returns The complete location
*/
setGeoLocation?(location: Partial<Location>): Promise<void>;
setGeoLocation?(location: Partial<Location>): Promise<Location>;
// MJSONWIRE
@@ -1880,8 +1852,10 @@ export interface ExternalDriver<C extends Constraints = Constraints, Ctx = strin
* @see {@link https://github.com/SeleniumHQ/mobile-spec/blob/master/spec-draft.md#device-modes}
*
* @param type - the bitmask representing network state
* @returns A number which is a bitmask representing categories like Data, Wifi, and Airplane
* mode status
*/
setNetworkConnection?(type: number): Promise<void>;
setNetworkConnection?(type: number): Promise<number>;
/**
* Get the current rotation state of the device
@@ -2044,11 +2018,14 @@ export interface ExtraDriverOpts {
skipUninstall?: boolean;
}
/**
* Options as passed into a driver constructor, which is just a union of {@linkcode ServerArgs} and {@linkcode Capabilities}.
*
* The combination happens within Appium prior to calling the constructor.
* Options as set within {@linkcode ExternalDriver.createSession}, which is a union of {@linkcode InitialOpts} and {@linkcode DriverCaps}.
*/
export type DriverOpts<C extends Constraints> = ServerArgs & ExtraDriverOpts & DriverCaps<C>;
export type DriverOpts<C extends Constraints> = InitialOpts & DriverCaps<C>;
/**
* Options as provided to the {@linkcode Driver} constructor.
*/
export type InitialOpts = Merge<ServerArgs, ExtraDriverOpts>;
/**
* An instance method of a driver class, whose name may be referenced by {@linkcode MethodDef.command}, and serves as an Appium command.
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/types",
"version": "0.12.0",
"version": "0.13.2",
"description": "Various type declarations used across Appium",
"keywords": [
"automation",
@@ -33,16 +33,16 @@
],
"scripts": {
"build": "node ./scripts/generate-schema-types.js",
"clean": "git checkout -- ./types/lib/appium-config.ts || true",
"clean": "git checkout -- ./lib/appium-config.ts || true",
"test:smoke": "node ./index.js",
"test:types": "tsd"
},
"dependencies": {
"@appium/schema": "^0.3.0",
"@appium/schema": "^0.3.1",
"@appium/tsconfig": "^0.3.0",
"@types/express": "4.17.17",
"@types/npmlog": "4.1.4",
"@types/ws": "8.5.4",
"@types/ws": "8.5.5",
"type-fest": "3.11.1"
},
"engines": {
+1
View File
@@ -27,6 +27,7 @@
"figures",
"find-up",
"get-port",
"get-stream",
"globby",
"got",
"inquirer",