Compare commits

...
Author SHA1 Message Date
Christopher Hiller f1e0a46712 chore: publish
- appium@2.0.0-beta.53
 - @appium/base-driver@9.3.0
 - @appium/base-plugin@2.2.0
 - @appium/doctor@2.0.6
 - @appium/docutils@0.1.6
 - @appium/driver-test-support@0.3.6
 - @appium/fake-driver@5.1.4
 - @appium/fake-plugin@3.1.4
 - @appium/plugin-test-support@0.3.6
 - @appium/support@3.1.4
 - @appium/test-support@3.0.6
 - @appium/typedoc-plugin-appium@0.3.4
 - @appium/types@0.9.0
2023-01-23 12:49:31 -08:00
Jonathan Lipps 8295e3f956 chore(types): commit auto-generated lint update 2023-01-23 12:32:42 -08:00
renovate[bot] 254f82402e chore(deps): update dependency json-schema-to-typescript to v11.0.3 2023-01-21 11:06:46 +00:00
renovate[bot] 6c4ba8caa5 fix(types): update dependency type-fest to v3.5.3 2023-01-21 02:08:38 +00:00
Christopher Hiller 12245ae98c chore(ci): add job to disallow merges of PRs
...if it has the "On Hold" label
2023-01-20 15:01:06 -08:00
Christopher Hiller 96eb4d7b3f chore(types): remove @wdio/types
Due to problems where multiple versions of `@wdio/types` can be installed in the dep tree of external modules, and the fact we are not using most of the types we pull in, it makes sense to remove this module.

The "standard" W3C caps have been pulled out of `@wdio/types`.  We do not need any webdriverio or vendor-specific cap types.  Those only make sense when consuming wdio itself and/or writing client-side code.

This will also make it easier to upgrade `webdriverio`; it too depends on `@wdio/types`.

Note: there were several Appium-specific caps in `@wdio/types` that I did not recognize.  Perhaps these were driver-specific and not accurately labeled as such.  Driver-specific caps belong in drivers.
2023-01-20 14:57:24 -08:00
Jonathan Lipps 11015b8871 test(appium): add e2e tests for plugin use of executeMethod(Map) 2023-01-20 14:21:08 -08:00
Christopher Hiller de6e83d196 chore(appium,types): rename cli command types
`PluginCommand` and `DriverCommand` both conflicted with `PluginCommand` and `DriverCommand` in `@appium/types`.  The former are string literals representing CLI args; the latter represent methods on plugin and driver classes.

This renames the former to make it clear it's CLI-specific
2023-01-20 14:21:08 -08:00
Christopher Hiller b8b7aae060 chore(types): tweak Plugin a little bit more
- `onUnexpectedShutdown` will always receive an `ExternalDriver` in a `Plugin`
- `handle` is actually a "known" `PluginCommand`
2023-01-20 14:21:08 -08:00
Christopher Hiller 9cd228247a chore: update MethodMap/ExecuteMethodMap to support plugins 2023-01-20 14:21:08 -08:00
Jonathan Lipps 84abed920a feat(base-plugin): add ability for plugins to implement execute methods 2023-01-20 14:21:08 -08:00
Christopher Hiller a96d952a06 chore(ci): add doc build to ci 2023-01-20 10:31:46 -08:00
renovate[bot] 854c5ec946 fix(support): update dependency @types/glob to v8.0.1 2023-01-20 16:23:41 +00:00
renovate[bot] 6726f6ddb5 chore(docutils): update dependency mkdocs-material to v9.0.6 2023-01-20 12:42:33 +00:00
Christopher Hiller 108c1abae0 chore(typedoc-plugin-appium): disable sorting
Sorting is handled by typedoc and it supersedes whatever we do with it.  The correct way to implement a custom sort would be...something else.  YAGNI for now
2023-01-19 14:31:43 -08:00
Christopher Hiller ec48c9cea7 fix(typedoc-plugin-appium): non-appium theme should not cause a fatal error
This was preventing tests from running
2023-01-19 14:31:43 -08:00
Christopher Hiller 4cb9bec7a0 chore(typedoc-plugin-appium): remove cruft 2023-01-19 14:31:43 -08:00
Christopher Hiller 92a45be902 chore(typedoc-plugin-appium): reorganize the tests
many of these were actually E2E tests (and slow)
2023-01-19 14:31:43 -08:00
Christopher Hiller a8365391dc chore(fake-driver): annihilate loathsome mixin classes
I did here what I did to `appium-xcuitest-driver`, which was to assign the command methods to the class as fields.  Easier this way.
2023-01-19 14:31:43 -08:00
Christopher Hiller 18772f4f0d fix(docs): fix filename of basedriver commands
I'm unsure about a) where the filename I just changed came from, and b) if we have control over the filename, and c) if so, how much control.

But anyway: it seems to generate a file named `appium_base_driver-1._appium_base_driver.md`.
2023-01-17 11:33:12 -08:00
Christopher Hiller d0e1cb2f65 fix(typedoc-plugin-appium): reduce severity of "missing method" error
This is either a bug in the plugin or a bug in `@appium/base-driver` (tbd).  But it was causing `typedoc` to fail with a fatal error, and we don't want that to happen (yet).  This change punts on the problem to get the docs build working
2023-01-17 11:33:12 -08:00
Christopher Hiller ed1edab209 fix(typedoc-plugin-appium): fix keywords for typedoc plugin autodetection 2023-01-17 11:33:12 -08:00
Christopher Hiller 52560a41b3 chore(scripts): fix typo in sync-pkgs script
The typo caused the `keywords` field in `packages/typedoc-plugin-appium/package.json` to be overwritten.  Because of this, the `keywords` field lost the magic keyword that `typedoc` uses to automatically detect a plugin.  Thus, `@appium/typedoc-plugin-appium` could not be found, and its specific options caused `typedoc` to fail.
2023-01-17 11:33:12 -08:00
renovate[bot] f76a5a71c9 fix(doctor): update dependency appium-adb to v9.10.24 2023-01-17 15:08:06 +00:00
renovate[bot] 8b15e2ca3a chore(deps): update dependency eslint-plugin-import to v2.27.5 2023-01-17 12:02:35 +00:00
renovate[bot] d7b35ab28b fix(support): update dependency glob to v8.1.0 2023-01-16 12:46:32 +00:00
renovate[bot] 54fdcea08a chore(deps): update dependency eslint to v8.32.0 2023-01-15 21:09:46 +00:00
renovate[bot] 64fd8ce940 fix(types): update dependency type-fest to v3.5.2 2023-01-15 17:22:46 +00:00
renovate[bot] 34081b44c8 fix(doctor): update dependency appium-adb to v9.10.23 2023-01-15 14:12:40 +00:00
renovate[bot] 12afa8934a chore(docutils): update dependency mkdocs-material to v9.0.5 2023-01-15 10:27:54 +00:00
renovate[bot] 3b213d40e7 fix(doctor): update dependency appium-adb to v9.10.22 2023-01-14 13:52:57 +00:00
renovate[bot] 8466cf6fcb chore(deps): update dependency prettier to v2.8.3 2023-01-14 11:00:36 +00:00
renovate[bot] 5c2168fb09 chore(deps): update dependency lerna to v6.4.1 2023-01-14 00:51:50 +00:00
Jonathan Lipps 67c9bdfbce chore: publish
- appium@2.0.0-beta.52
 - @appium/base-driver@9.2.3
 - @appium/base-plugin@2.1.3
 - @appium/doctor@2.0.5
 - @appium/docutils@0.1.5
 - @appium/driver-test-support@0.3.5
 - @appium/execute-driver-plugin@3.0.5
 - @appium/fake-driver@5.1.3
 - @appium/fake-plugin@3.1.3
 - @appium/images-plugin@2.0.5
 - @appium/opencv@2.0.5
 - @appium/plugin-test-support@0.3.5
 - @appium/relaxed-caps-plugin@1.0.4
 - @appium/schema@0.2.3
 - @appium/support@3.1.3
 - @appium/test-support@3.0.5
 - @appium/tsconfig@0.2.3
 - @appium/typedoc-plugin-appium@0.3.3
 - @appium/types@0.8.3
 - @appium/universal-xml-plugin@1.0.4
2023-01-13 13:28:45 -08:00
Jonathan Lipps 9e0a313d7c chore: update lerna git head 2023-01-13 13:26:36 -08:00
85 changed files with 1928 additions and 1357 deletions
+19 -1
View File
@@ -38,10 +38,28 @@ jobs:
uses: bahmutov/npm-install@1a235c31658a322a3b024444759650ee6345c26d # tag=v1
with:
useRollingCache: true
install-command: npm ci --foreground-scripts
install-command: npm ci
- name: ESLint
run: npm run lint
- name: Validate Renovate Config
uses: rinchsan/renovate-config-validator@1ea1e8514f6a33fdd71c40b0a5fa3512b9e7b936 # tag=v0
with:
pattern: '{.renovaterc.json,renovate/default.json}'
docs:
name: Docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- name: Install dependencies (node)
uses: bahmutov/npm-install@1a235c31658a322a3b024444759650ee6345c26d # tag=v1
with:
useRollingCache: true
install-command: npm ci
- name: Install dependencies (python)
run: pip install -r packages/docutils/requirements.txt
- name: Build Docs
run: |
git config user.name 'Appium Bot'
git config user.email 'appium@appium.io'
npm run --workspace packages/appium build:docs
+15
View File
@@ -0,0 +1,15 @@
name: Disallow "On Hold" PRs
on:
pull_request:
types: [opened, labeled, unlabeled, synchronize]
jobs:
label-check:
if: github.base_ref == 'master'
runs-on: ubuntu-latest
steps:
- uses: danielchabr/pr-labels-checker@e1d7e79aa0933af1728011705a30528a279874fd
with:
id: check-labels
hasNone: On Hold
githubToken: ${{ secrets.GITHUB_TOKEN }}
+436 -432
View File
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -53,7 +53,7 @@
"sync-pkgs": "run-p sync-pkgs:*",
"sync-pkgs:appium-readme": "sync-monorepo-packages --force --no-package-json --packages=packages/appium README.md",
"sync-pkgs:common-fields": "sync-monorepo-packages --fields=author,license,bugs,homepage,engines",
"sync-pkgs:keywords": "sync-monorepo-packages --field=keywords --packages=\"packages/*\" --packages=\"!packages/eslint-config-appium\" --packages=\"!packages/types\" --packages\"!packages/typedoc-plugin-appium\"",
"sync-pkgs:keywords": "sync-monorepo-packages --field=keywords --packages=\"packages/*\" --packages=\"!packages/eslint-config-appium\" --packages=\"!packages/types\" --packages=\"!packages/typedoc-plugin-appium\"",
"sync-pkgs:license": "sync-monorepo-packages --force --no-package-json LICENSE",
"stage-synced-pkgs": "git add -A packages/appium/README.md \"packages/*/package.json\"",
"test": "npm-run-all -p lint build -s test:unit",
@@ -91,10 +91,10 @@
"chai-as-promised": "7.1.1",
"chai-webdriverio-async": "2.7.0",
"cpy-cli": "4.2.0",
"eslint": "8.31.0",
"eslint": "8.32.0",
"eslint-config-prettier": "8.6.0",
"eslint-find-rules": "4.1.0",
"eslint-plugin-import": "2.27.4",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-mocha": "10.1.0",
"eslint-plugin-promise": "6.1.1",
"fancy-log": "2.0.0",
@@ -102,8 +102,8 @@
"get-port": "5.1.1",
"handlebars": "4.7.7",
"husky": "8.0.3",
"json-schema-to-typescript": "11.0.2",
"lerna": "6.4.0",
"json-schema-to-typescript": "11.0.3",
"lerna": "6.4.1",
"lint-staged": "13.1.0",
"log-symbols": "4.1.0",
"midnight-smoker": "2.0.1",
@@ -111,7 +111,7 @@
"mjpeg-server": "0.3.1",
"mocha": "10.2.0",
"npm-run-all": "4.1.5",
"prettier": "2.8.2",
"prettier": "2.8.3",
"rewiremock": "3.14.4",
"rimraf": "3.0.2",
"serve-static": "1.15.0",
+22
View File
@@ -3,6 +3,28 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.0.0-beta.53](https://github.com/appium/appium/compare/appium@2.0.0-beta.52...appium@2.0.0-beta.53) (2023-01-23)
### Bug Fixes
* **docs:** fix filename of basedriver commands ([18772f4](https://github.com/appium/appium/commit/18772f4f0d04d4c27135b6a66732bd9518568bdf))
* **support:** update dependency glob to v8.1.0 ([d7b35ab](https://github.com/appium/appium/commit/d7b35ab28b8afd0f93f775a223373956a57ee881))
* **types:** update dependency type-fest to v3.5.2 ([64fd8ce](https://github.com/appium/appium/commit/64fd8ce94018b0bb7ccb2baade8d525703f41c45))
* **types:** update dependency type-fest to v3.5.3 ([6c4ba8c](https://github.com/appium/appium/commit/6c4ba8caa508840640f05eea1ab41ecb290312aa))
# [2.0.0-beta.52](https://github.com/appium/appium/compare/appium@2.0.0-beta.51...appium@2.0.0-beta.52) (2023-01-13)
**Note:** Version bump only for package appium
# [2.0.0-beta.51](https://github.com/appium/appium/compare/appium@2.0.0-beta.50...appium@2.0.0-beta.51) (2023-01-13)
**Note:** Version bump only for package appium
@@ -7,7 +7,9 @@ const path = require('path');
const monorepoRoot = path.resolve(__dirname, '..', '..', '..', '..');
const {exec} = require('teen_process');
const typedocMap = [[['commands', 'appium_base_driver.md'], ['base_driver.md']]];
const typedocMap = [
[['commands', 'appium_base_driver-1._appium_base_driver.md'], ['base_driver.md']],
];
async function main() {
log.info('Generating typedoc reference material');
+1 -1
View File
@@ -89,7 +89,7 @@ class ArgParser {
* If no subcommand is passed in, this method will inject the `server` subcommand.
*
* `ArgParser.prototype.parse_args` is an alias of this method.
* @template {import('appium/types').CliCommand} [Cmd=import('appium/types').ServerCommand]
* @template {import('appium/types').CliCommand} [Cmd=import('appium/types').CliCommandServer]
* @param {string[]} [args] - Array of arguments, ostensibly from `process.argv`. Gathers args from `process.argv` if not provided.
* @returns {import('appium/types').Args<Cmd>} - The parsed arguments
*/
+4 -4
View File
@@ -139,7 +139,7 @@ function getServerUpdaters(driverClasses, pluginClasses) {
* Makes a big `MethodMap` from all the little `MethodMap`s in the extensions
* @param {DriverNameMap} driverClasses
* @param {PluginNameMap} pluginClasses
* @returns {import('@appium/types').MethodMap}
* @returns {import('@appium/types').MethodMap<import('@appium/types').Driver>}
*/
function getExtraMethodMap(driverClasses, pluginClasses) {
return [...driverClasses.keys(), ...pluginClasses.keys()].reduce(
@@ -400,9 +400,9 @@ export {main, init, resolveAppiumHome};
* @typedef {import('appium/types').CliCommand} CliCommand
* @typedef {import('appium/types').CliExtensionSubcommand} CliExtensionSubcommand
* @typedef {import('appium/types').CliExtensionCommand} CliExtensionCommand
* @typedef {import('appium/types').ServerCommand} ServerCommand
* @typedef {import('appium/types').DriverCommand} DriverCommand
* @typedef {import('appium/types').PluginCommand} PluginCommand
* @typedef {import('appium/types').CliCommandServer} ServerCommand
* @typedef {import('appium/types').CliCommandDriver} DriverCommand
* @typedef {import('appium/types').CliCommandPlugin} PluginCommand
* @typedef {import('./extension').DriverNameMap} DriverNameMap
* @typedef {import('./extension').PluginNameMap} PluginNameMap
*/
+3 -3
View File
@@ -403,9 +403,9 @@ export {
* @typedef {import('appium/types').CliCommand} CliCommand
* @typedef {import('appium/types').CliExtensionSubcommand} CliExtensionSubcommand
* @typedef {import('appium/types').CliExtensionCommand} CliExtensionCommand
* @typedef {import('appium/types').ServerCommand} ServerCommand
* @typedef {import('appium/types').DriverCommand} DriverCommand
* @typedef {import('appium/types').PluginCommand} PluginCommand
* @typedef {import('appium/types').CliCommandServer} ServerCommand
* @typedef {import('appium/types').CliCommandDriver} DriverCommand
* @typedef {import('appium/types').CliCommandPlugin} PluginCommand
*/
/**
+10 -10
View File
@@ -1,6 +1,6 @@
{
"name": "appium",
"version": "2.0.0-beta.51",
"version": "2.0.0-beta.53",
"description": "Automation for Apps.",
"keywords": [
"automation",
@@ -58,12 +58,12 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/base-driver": "^9.2.2",
"@appium/base-plugin": "^2.1.2",
"@appium/docutils": "^0.1.4",
"@appium/schema": "^0.2.2",
"@appium/support": "^3.1.2",
"@appium/types": "^0.8.2",
"@appium/base-driver": "^9.3.0",
"@appium/base-plugin": "^2.2.0",
"@appium/docutils": "^0.1.6",
"@appium/schema": "^0.2.3",
"@appium/support": "^3.1.4",
"@appium/types": "^0.9.0",
"@sidvind/better-ajv-errors": "2.1.0",
"@types/argparse": "2.0.10",
"@types/bluebird": "3.5.38",
@@ -80,7 +80,7 @@
"bluebird": "3.7.2",
"cross-env": "7.0.3",
"find-up": "5.0.0",
"glob": "8.0.3",
"glob": "8.1.0",
"lilconfig": "2.0.6",
"lodash": "4.17.21",
"longjohn": "0.2.12",
@@ -91,7 +91,7 @@
"semver": "7.3.8",
"source-map-support": "0.5.21",
"teen_process": "2.0.2",
"type-fest": "3.5.1",
"type-fest": "3.5.3",
"winston": "3.8.2",
"wrap-ansi": "7.0.0",
"yaml": "2.2.1"
@@ -104,7 +104,7 @@
"access": "public",
"tag": "next"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd",
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72",
"typedoc": {
"entryPoint": "./lib/main.js"
}
@@ -328,6 +328,50 @@ describe('FakePlugin w/ FakeDriver via HTTP', function () {
});
});
});
describe('Execute Methods', function () {
/** @type {AppiumServer} */
let server;
/** @type {import('webdriverio').Browser<'async'>} */
let driver;
before(async function () {
// then start server if we need to
const args = {
appiumHome,
port,
address: TEST_HOST,
usePlugins: ['fake'],
useDrivers: ['fake'],
};
server = /** @type {AppiumServer} */ (await appiumServer(args));
driver = await wdio(wdOpts);
});
after(async function () {
if (driver) {
await driver.deleteSession();
}
if (server) {
await server.close();
}
});
it('should handle execute methods using executeMethodMap', async function () {
const res = await driver.executeScript('fake: plugMeIn', [{socket: 'electrical'}]);
res.should.eql('Plugged in to electrical');
});
it('should handle execute methods overridden on the driver', async function () {
const res = await driver.executeScript('fake: getThing', []);
res.should.eql('PLUGIN_FAKE_THING');
});
it('should let driver handle unknown execute methods', async function () {
const sum = await driver.executeScript('fake: addition', [{num1: 2, num2: 3}]);
sum.should.eql(5);
});
});
});
/**
+18 -14
View File
@@ -1,23 +1,23 @@
import {DriverType, PluginType, ServerArgs} from '@appium/types';
import {SetOptional} from 'type-fest';
import {InstallType} from './manifest';
export type ServerCommand = 'server';
export type DriverCommand = DriverType;
export type PluginCommand = PluginType;
export type CliCommandServer = 'server';
export type CliCommandDriver = DriverType;
export type CliCommandPlugin = PluginType;
/**
* Extension-specific commands
*/
export type CliExtensionCommand = DriverCommand | PluginCommand;
export type CliExtensionCommand = CliCommandDriver | CliCommandPlugin;
/**
* Possible commands for the `appium` CLI.
*/
export type CliCommand = ServerCommand | CliExtensionCommand;
export type CliCommand = CliCommandServer | CliExtensionCommand;
/**
* Possible subcommands of {@linkcode DriverCommand} or
* {@linkcode PluginCommand}.
* Possible subcommands of {@linkcode CliCommandDriver} or
* {@linkcode CliCommandPlugin}.
*/
export type CliExtensionSubcommand = 'install' | 'list' | 'run' | 'uninstall' | 'update';
@@ -41,7 +41,7 @@ export interface CliExtensionSubcommandUpdateArgs {
*/
export interface MoreArgs {
/**
* Possible subcommands. If empty, defaults to {@linkcode ServerCommand}.
* Possible subcommands. If empty, defaults to {@linkcode CliCommandServer}.
*/
subcommand?: CliCommand;
@@ -134,7 +134,11 @@ export type ExtArgs<
Cmd extends CliExtensionCommand,
SubCmd extends CliExtensionSubcommand
> = BaseExtArgs<Cmd> &
(Cmd extends DriverCommand ? DriverExtArgs : Cmd extends PluginCommand ? PluginExtArgs : never) &
(Cmd extends CliCommandDriver
? DriverExtArgs
: Cmd extends CliCommandPlugin
? PluginExtArgs
: never) &
(SubCmd extends 'install'
? CliExtensionSubcommandInstallArgs
: SubCmd extends 'list'
@@ -147,11 +151,11 @@ export type ExtArgs<
* Some generic bits of arguments; should not be used outside this declaration
*/
export type CommonArgs<
Cmd extends CliCommand = ServerCommand,
Cmd extends CliCommand = CliCommandServer,
SubCmd extends CliExtensionSubcommand | void = void
> = MoreArgs &
ProgrammaticArgs &
(Cmd extends ServerCommand
(Cmd extends CliCommandServer
? ServerArgs
: Cmd extends CliExtensionCommand
? SubCmd extends CliExtensionSubcommand
@@ -163,7 +167,7 @@ export type CommonArgs<
* Fully-parsed arguments, containing defaults, computed args, and config file values.
*/
export type ParsedArgs<
Cmd extends CliCommand = ServerCommand,
Cmd extends CliCommand = CliCommandServer,
SubCmd extends CliExtensionSubcommand | void = void
> = CommonArgs<Cmd, SubCmd>;
@@ -173,9 +177,9 @@ export type ParsedArgs<
* _May_ have defaults applied; _may_ contain config values; _may_ contain computed args.
*/
export type Args<
Cmd extends CliCommand = ServerCommand,
Cmd extends CliCommand = CliCommandServer,
SubCmd extends CliExtensionSubcommand | void = void
> = Cmd extends ServerCommand
> = Cmd extends CliCommandServer
? SetOptional<CommonArgs<Cmd>, keyof ServerArgs>
: ParsedArgs<Cmd, SubCmd>;
+25
View File
@@ -3,6 +3,31 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [9.3.0](https://github.com/appium/appium/compare/@appium/base-driver@9.2.3...@appium/base-driver@9.3.0) (2023-01-23)
### Bug Fixes
* **types:** update dependency type-fest to v3.5.2 ([64fd8ce](https://github.com/appium/appium/commit/64fd8ce94018b0bb7ccb2baade8d525703f41c45))
* **types:** update dependency type-fest to v3.5.3 ([6c4ba8c](https://github.com/appium/appium/commit/6c4ba8caa508840640f05eea1ab41ecb290312aa))
### Features
* **base-plugin:** add ability for plugins to implement execute methods ([84abed9](https://github.com/appium/appium/commit/84abed920a1dc796ff09013ce86079de5a25fe50))
## [9.2.3](https://github.com/appium/appium/compare/@appium/base-driver@9.2.2...@appium/base-driver@9.2.3) (2023-01-13)
**Note:** Version bump only for package @appium/base-driver
## [9.2.2](https://github.com/appium/appium/compare/@appium/base-driver@9.2.1...@appium/base-driver@9.2.2) (2023-01-13)
**Note:** Version bump only for package @appium/base-driver
@@ -1,5 +1,5 @@
import _ from 'lodash';
import {errors, makeArgs, checkParams} from '../../protocol';
import {errors, validateExecuteMethodParams} from '../../protocol';
/**
* @template {Constraints} C
@@ -16,23 +16,6 @@ export function ExecuteMixin(Base) {
* @param {[Record<string, any>]|[]} protoArgs
*/
async executeMethod(script, protoArgs) {
// the w3c protocol will give us an array of arguments to apply to a javascript function.
// that's not what we're doing. we're going to look for a JS object as the first arg, so we
// can perform validation on it. we'll ignore everything else.
if (!protoArgs || !_.isArray(protoArgs) || protoArgs.length > 1) {
throw new errors.InvalidArgumentError(
`Did not get correct format of arguments for execute method. Expected zero or one ` +
`arguments to execute script and instead received: ${JSON.stringify(protoArgs)}`
);
}
let args = protoArgs[0] ?? {};
if (!_.isPlainObject(args)) {
throw new errors.InvalidArgumentError(
`Did not receive an appropriate execute method parameters object. It needs to be ` +
`deserializable as a plain JS object`
);
}
const Driver = /** @type {DriverClass} */ (this.constructor);
const commandMetadata = {...Driver.executeMethodMap?.[script]};
if (!commandMetadata.command) {
@@ -42,16 +25,8 @@ export function ExecuteMixin(Base) {
`are: ${availableScripts.join(', ')}`
);
}
let argsToApply = [];
if (!commandMetadata.params) {
commandMetadata.params = {required: [], optional: []};
} else {
commandMetadata.params.required ??= [];
commandMetadata.params.optional ??= [];
checkParams(commandMetadata.params, args, null);
}
argsToApply = makeArgs({}, args, commandMetadata.params, null);
return await this[commandMetadata.command](...argsToApply);
const args = validateExecuteMethodParams(protoArgs, commandMetadata.params);
return await this[commandMetadata.command](...args);
}
}
return ExecuteCommands;
@@ -7,6 +7,7 @@ import {
GET_STATUS_COMMAND,
makeArgs,
checkParams,
validateExecuteMethodParams,
} from './protocol';
import {NO_SESSION_ID_COMMANDS, ALL_COMMANDS, METHOD_MAP, routeToCommandName} from './routes';
import {errors, isErrorType, errorFromMJSONWPStatusCode, errorFromW3CJsonCode} from './errors';
@@ -17,6 +18,7 @@ export {
isErrorType,
makeArgs,
checkParams,
validateExecuteMethodParams,
errorFromMJSONWPStatusCode,
errorFromW3CJsonCode,
ALL_COMMANDS,
@@ -215,6 +215,34 @@ export function makeArgs(requestParams, jsonObj, payloadParams, protocol) {
return args;
}
function validateExecuteMethodParams(params, paramSpec) {
// the w3c protocol will give us an array of arguments to apply to a javascript function.
// that's not what we're doing. we're going to look for a JS object as the first arg, so we
// can perform validation on it. we'll ignore everything else.
if (!params || !_.isArray(params) || params.length > 1) {
throw new errors.InvalidArgumentError(
`Did not get correct format of arguments for execute method. Expected zero or one ` +
`arguments to execute script and instead received: ${JSON.stringify(params)}`
);
}
const args = params[0] ?? {};
if (!_.isPlainObject(args)) {
throw new errors.InvalidArgumentError(
`Did not receive an appropriate execute method parameters object. It needs to be ` +
`deserializable as a plain JS object`
);
}
if (!paramSpec) {
paramSpec = {required: [], optional: []};
} else {
paramSpec.required ??= [];
paramSpec.optional ??= [];
checkParams(paramSpec, args, null);
}
const argsToApply = makeArgs({}, args, paramSpec, null);
return argsToApply;
}
/**
*
* @param {import('@appium/types').Core} driver
@@ -526,4 +554,5 @@ export {
DELETE_SESSION_COMMAND,
GET_STATUS_COMMAND,
deprecatedCommandsLogged,
validateExecuteMethodParams,
};
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/base-driver",
"version": "9.2.2",
"version": "9.3.0",
"description": "Base driver class for Appium drivers",
"keywords": [
"automation",
@@ -42,8 +42,8 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/support": "^3.1.2",
"@appium/types": "^0.8.2",
"@appium/support": "^3.1.4",
"@appium/types": "^0.9.0",
"@colors/colors": "1.5.0",
"@types/async-lock": "1.3.0",
"@types/bluebird": "3.5.38",
@@ -64,7 +64,7 @@
"morgan": "1.10.0",
"serve-favicon": "2.5.0",
"source-map-support": "0.5.21",
"type-fest": "3.5.1",
"type-fest": "3.5.3",
"validate.js": "0.13.1"
},
"engines": {
@@ -74,7 +74,7 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd",
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72",
"typedoc": {
"entryPoint": "./lib/index.js"
}
+19
View File
@@ -3,6 +3,25 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.2.0](https://github.com/appium/appium/compare/@appium/base-plugin@2.1.3...@appium/base-plugin@2.2.0) (2023-01-23)
### Features
* **base-plugin:** add ability for plugins to implement execute methods ([84abed9](https://github.com/appium/appium/commit/84abed920a1dc796ff09013ce86079de5a25fe50))
## [2.1.3](https://github.com/appium/appium/compare/@appium/base-plugin@2.1.2...@appium/base-plugin@2.1.3) (2023-01-13)
**Note:** Version bump only for package @appium/base-plugin
## [2.1.2](https://github.com/appium/appium/compare/@appium/base-plugin@2.1.1...@appium/base-plugin@2.1.2) (2023-01-13)
**Note:** Version bump only for package @appium/base-plugin
+52
View File
@@ -1,4 +1,5 @@
import {logger} from '@appium/support';
import {validateExecuteMethodParams} from '@appium/base-driver';
/**
* @implements {Plugin}
@@ -21,6 +22,24 @@ class BasePlugin {
*/
static newMethodMap = {};
/**
* Subclasses should use type `import('@appium/types').ExecuteMethodMap<SubclassName>`.
*
* Building up this map allows the use of the convenience function `executeMethod`, which
* basically does verification of names and parameters for execute methods implemented by this
* plugin.
*
* ```ts
* static executeMethodMap = {
* 'foo: bar': {
* command: 'commandName',
* params: {required: ['thing1', 'thing2'], optional: ['thing3']},
* },
* } as const;
* ```
*/
static executeMethodMap = {};
/**
* @param {string} name
* @param {Record<string,unknown>} [cliArgs]
@@ -30,6 +49,36 @@ class BasePlugin {
this.cliArgs = cliArgs;
this.logger = logger.getLogger(`Plugin [${name}]`);
}
/**
* A convenience method that can be called by plugins who implement their own `executeMethodMap`.
* Only useful if your plugin has defined `executeMethodMap`. This helper requires passing in the
* `next` and `driver` objects since naturally we'd want to make sure to trigger the driver's own
* `executeMethod` call if an execute method is not found on the plugin itself.
*
* @template {Driver} D
* @param {NextPluginCallback} next
* @param {D} driver
* @param {string} script
* @param {[Record<string, any>]|[]} protoArgs
* @this {Plugin}
*/
async executeMethod(next, driver, script, protoArgs) {
const Plugin = /** @type {PluginClass} */ (this.constructor);
const commandMetadata = {...Plugin.executeMethodMap?.[script]};
/** @type {import('@appium/types').PluginCommand<D>|undefined} */
let command;
if (!commandMetadata.command || !(command = this[commandMetadata.command])) {
this.logger.info(
`Plugin did not know how to handle method '${script}'. Passing control to next`
);
return await next();
}
const args = validateExecuteMethodParams(protoArgs, commandMetadata.params);
return await command.call(this, next, driver, ...args);
}
}
export default BasePlugin;
@@ -37,4 +86,7 @@ export {BasePlugin};
/**
* @typedef {import('@appium/types').Plugin} Plugin
* @typedef {import('@appium/types').NextPluginCallback} NextPluginCallback
* @typedef {import('@appium/types').Driver} Driver
* @typedef {import('@appium/types').PluginClass} PluginClass
*/
+4 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/base-plugin",
"version": "2.1.2",
"version": "2.2.0",
"description": "The base plugin used to create Appium 2.0 plugins",
"keywords": [
"automation",
@@ -39,7 +39,8 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/support": "^3.1.2"
"@appium/base-driver": "^9.3.0",
"@appium/support": "^3.1.4"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
@@ -48,7 +49,7 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd",
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72",
"tags": [
"appium"
],
+21
View File
@@ -3,6 +3,27 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.0.6](https://github.com/appium/appium/compare/@appium/doctor@2.0.5...@appium/doctor@2.0.6) (2023-01-23)
### Bug Fixes
* **doctor:** update dependency appium-adb to v9.10.22 ([3b213d4](https://github.com/appium/appium/commit/3b213d40e72ccec850f5efb48777b0aee2918cc4))
* **doctor:** update dependency appium-adb to v9.10.23 ([34081b4](https://github.com/appium/appium/commit/34081b44c88a4b2d820eed864c1e9ab36c217d2c))
* **doctor:** update dependency appium-adb to v9.10.24 ([f76a5a7](https://github.com/appium/appium/commit/f76a5a71c96cddac5ad8b8f12d2c03270a28e330))
## [2.0.5](https://github.com/appium/appium/compare/@appium/doctor@2.0.4...@appium/doctor@2.0.5) (2023-01-13)
**Note:** Version bump only for package @appium/doctor
## [2.0.4](https://github.com/appium/appium/compare/@appium/doctor@2.0.3...@appium/doctor@2.0.4) (2023-01-13)
**Note:** Version bump only for package @appium/doctor
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/doctor",
"version": "2.0.4",
"version": "2.0.6",
"description": "Test environment for fitness to run Appium",
"keywords": [
"automation",
@@ -43,11 +43,11 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/support": "^3.1.2",
"@appium/support": "^3.1.4",
"@colors/colors": "1.5.0",
"@types/bluebird": "3.5.38",
"@types/teen_process": "2.0.0",
"appium-adb": "9.10.21",
"appium-adb": "9.10.24",
"bluebird": "3.7.2",
"inquirer": "8.2.5",
"lodash": "4.17.21",
@@ -62,5 +62,5 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd"
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72"
}
+16
View File
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.1.6](https://github.com/appium/appium/compare/@appium/docutils@0.1.5...@appium/docutils@0.1.6) (2023-01-23)
**Note:** Version bump only for package @appium/docutils
## [0.1.5](https://github.com/appium/appium/compare/@appium/docutils@0.1.4...@appium/docutils@0.1.5) (2023-01-13)
**Note:** Version bump only for package @appium/docutils
## [0.1.4](https://github.com/appium/appium/compare/@appium/docutils@0.1.3...@appium/docutils@0.1.4) (2023-01-13)
**Note:** Version bump only for package @appium/docutils
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/docutils",
"version": "0.1.4",
"version": "0.1.6",
"description": "Documentation generation utilities for Appium and related projects",
"keywords": [
"automation",
@@ -42,7 +42,7 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/support": "^3.1.2",
"@appium/support": "^3.1.4",
"source-map-support": "0.5.21",
"teen_process": "2.0.2"
},
@@ -53,5 +53,5 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd"
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72"
}
+1 -1
View File
@@ -1,4 +1,4 @@
mkdocs==1.4.2
mkdocs-material==9.0.4
mkdocs-material==9.0.6
mkdocs-material-extensions==1.1.1
mike==1.1.2
+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.
## [0.3.6](https://github.com/appium/appium/compare/@appium/driver-test-support@0.3.5...@appium/driver-test-support@0.3.6) (2023-01-23)
### Bug Fixes
* **types:** update dependency type-fest to v3.5.2 ([64fd8ce](https://github.com/appium/appium/commit/64fd8ce94018b0bb7ccb2baade8d525703f41c45))
* **types:** update dependency type-fest to v3.5.3 ([6c4ba8c](https://github.com/appium/appium/commit/6c4ba8caa508840640f05eea1ab41ecb290312aa))
## [0.3.5](https://github.com/appium/appium/compare/@appium/driver-test-support@0.3.4...@appium/driver-test-support@0.3.5) (2023-01-13)
**Note:** Version bump only for package @appium/driver-test-support
## [0.3.4](https://github.com/appium/appium/compare/@appium/driver-test-support@0.3.3...@appium/driver-test-support@0.3.4) (2023-01-13)
**Note:** Version bump only for package @appium/driver-test-support
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/driver-test-support",
"version": "0.3.4",
"version": "0.3.6",
"description": "Test utilities for Appium drivers",
"keywords": [
"automation",
@@ -40,7 +40,7 @@
},
"types": "./build/lib/index.d.ts",
"dependencies": {
"@appium/types": "^0.8.2",
"@appium/types": "^0.9.0",
"@types/lodash": "4.14.191",
"axios": "1.2.2",
"bluebird": "3.7.2",
@@ -49,7 +49,7 @@
"lodash": "4.17.21",
"sinon": "15.0.1",
"source-map-support": "0.5.21",
"type-fest": "3.5.1"
"type-fest": "3.5.3"
},
"peerDependencies": {
"appium": "^2.0.0-beta.43",
@@ -62,5 +62,5 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd"
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72"
}
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.0.5](https://github.com/appium/appium/compare/@appium/execute-driver-plugin@3.0.4...@appium/execute-driver-plugin@3.0.5) (2023-01-13)
**Note:** Version bump only for package @appium/execute-driver-plugin
## [3.0.4](https://github.com/appium/appium/compare/@appium/execute-driver-plugin@3.0.3...@appium/execute-driver-plugin@3.0.4) (2023-01-13)
**Note:** Version bump only for package @appium/execute-driver-plugin
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/execute-driver-plugin",
"version": "3.0.4",
"version": "3.0.5",
"description": "Plugin for batching and executing driver commands with Appiums",
"keywords": [
"automation",
@@ -58,7 +58,7 @@
"pluginName": "execute-driver",
"mainClass": "ExecuteDriverPlugin"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd",
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72",
"typedoc": {
"entryPoint": "./lib/plugin.js"
}
+16
View File
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [5.1.4](https://github.com/appium/appium/compare/@appium/fake-driver@5.1.3...@appium/fake-driver@5.1.4) (2023-01-23)
**Note:** Version bump only for package @appium/fake-driver
## [5.1.3](https://github.com/appium/appium/compare/@appium/fake-driver@5.1.2...@appium/fake-driver@5.1.3) (2023-01-13)
**Note:** Version bump only for package @appium/fake-driver
## [5.1.2](https://github.com/appium/appium/compare/@appium/fake-driver@5.1.1...@appium/fake-driver@5.1.2) (2023-01-13)
**Note:** Version bump only for package @appium/fake-driver
+59 -68
View File
@@ -1,82 +1,73 @@
import {errors} from 'appium/driver';
/**
* @template {Class<import('../types').IContextsCommands & import('@appium/types').IFindCommands>} T
* @param {T} Base
* @returns {Class<AlertCommands>}
*/
export function AlertMixin(Base) {
export default {
/**
* @implements {IAlertCommands}
* @this {FakeDriver}
*/
class AlertCommands extends Base {
assertNoAlert() {
if (this.appModel.hasAlert()) {
throw new errors.UnexpectedAlertOpenError();
}
assertNoAlert() {
if (this.appModel.hasAlert()) {
throw new errors.UnexpectedAlertOpenError();
}
},
assertAlert() {
if (!this.appModel.hasAlert()) {
throw new errors.NoAlertOpenError();
}
/**
* @this {FakeDriver}
*/
assertAlert() {
if (!this.appModel.hasAlert()) {
throw new errors.NoAlertOpenError();
}
},
/**
* Get the text of an alert
*
* @returns {Promise<string>}
*/
async getAlertText() {
this.assertAlert();
return this.appModel.alertText();
/**
* Get the text of an alert
*
* @returns {Promise<string>}
* @this {FakeDriver}
*/
async getAlertText() {
this.assertAlert();
return this.appModel.alertText();
},
/**
* Set the text of an alert
*
* @param {string} text
* @returns {Promise<void>}
* @this {FakeDriver}
*/
async setAlertText(text) {
this.assertAlert();
try {
this.appModel.setAlertText(text);
} catch (e) {
throw new errors.InvalidElementStateError();
}
},
/**
* Set the text of an alert
*
* @param {string} text
* @returns {Promise<void>}
*/
async setAlertText(text) {
this.assertAlert();
try {
this.appModel.setAlertText(text);
} catch (e) {
throw new errors.InvalidElementStateError();
}
}
/**
* Accept an alert
*
* @returns {Promise<void>}
* @this {FakeDriver}
*/
async postAcceptAlert() {
this.assertAlert();
this.appModel.handleAlert();
},
/**
* Accept an alert
*
* @returns {Promise<void>}
*/
async postAcceptAlert() {
this.assertAlert();
this.appModel.handleAlert();
}
/**
* Dismiss an alert
*
* @returns {Promise<null>}
*/
postDismissAlert = this.postAcceptAlert;
}
return AlertCommands;
}
/**
* Dismiss an alert
*
* @returns {Promise<void>}
* @this {FakeDriver}
*/
async postDismissAlert() {
return this.postAcceptAlert();
},
};
/**
* @typedef {import('../driver').FakeDriverCore} FakeDriverCore
*/
/**
* @template T,[U={}],[V=Array<any>]
* @typedef {import('@appium/types').Class<T,U,V>} Class
*/
/**
* @typedef {import('../types').IAlertCommands} IAlertCommands
* @typedef {import('../driver').FakeDriver} FakeDriver
*/
+72 -81
View File
@@ -1,101 +1,92 @@
import _ from 'lodash';
import {errors} from 'appium/driver';
/**
*
* @template {Class<import('../types').IFakeDriver>} T
* @param {T} Base
*/
export function ContextsMixin(Base) {
export default {
/**
* @implements {IContextsCommands}
* @this {FakeDriver}
*/
class ContextsCommands extends Base {
getRawContexts() {
let contexts = {NATIVE_APP: null, PROXY: null};
let wvs = this.appModel?.getWebviews() ?? [];
for (let i = 1; i < wvs.length + 1; i++) {
contexts[`WEBVIEW_${i}`] = wvs[i - 1];
}
return contexts;
getRawContexts() {
let contexts = {NATIVE_APP: null, PROXY: null};
let wvs = this.appModel?.getWebviews() ?? [];
for (let i = 1; i < wvs.length + 1; i++) {
contexts[`WEBVIEW_${i}`] = wvs[i - 1];
}
return contexts;
},
assertWebviewContext() {
if (this.curContext === 'NATIVE_APP') {
throw new errors.InvalidContextError();
}
/**
* @this {FakeDriver}
*/
assertWebviewContext() {
if (this.curContext === 'NATIVE_APP') {
throw new errors.InvalidContextError();
}
},
// do not add a description to this method's docstring
/*
* @returns {Promise<string>}
*/
async getCurrentContext() {
return this.curContext;
}
/**
* @returns {Promise<string>}
* @this {FakeDriver}
*/
async getCurrentContext() {
return this.curContext;
},
/**
* Get the list of available contexts
*
* @returns {Promise<string[]>}
*/
async getContexts() {
return _.keys(this.getRawContexts());
}
/**
* Get the list of available contexts
*
* @returns {Promise<string[]>}
* @this {FakeDriver}
*/
async getContexts() {
return _.keys(this.getRawContexts());
},
/**
* Set the current context
*
* @param {string} context - name of the context
* @returns {Promise<void>}
*/
async setContext(context) {
let contexts = this.getRawContexts();
if (context in contexts) {
this.curContext = context;
if (context === 'NATIVE_APP') {
this.appModel.deactivateWebview();
this._proxyActive = false;
} else if (context === 'PROXY') {
this._proxyActive = true;
} else {
this.appModel.activateWebview(contexts[context]);
this._proxyActive = false;
}
/**
* Set the current context
*
* @param {string} context - name of the context
* @returns {Promise<void>}
* @this {FakeDriver}
*/
async setContext(context) {
let contexts = this.getRawContexts();
if (context in contexts) {
this.curContext = context;
if (context === 'NATIVE_APP') {
this.appModel.deactivateWebview();
this._proxyActive = false;
} else if (context === 'PROXY') {
this._proxyActive = true;
} else {
throw new errors.NoSuchContextError();
this.appModel.activateWebview(contexts[context]);
this._proxyActive = false;
}
} else {
throw new errors.NoSuchContextError();
}
},
/**
* Set the active frame
*
* @param {number} frameId
* @returns {Promise<void>}
*/
async setFrame(frameId) {
this.assertWebviewContext();
if (frameId === null) {
this.appModel.deactivateFrame();
} else {
let nodes = this.appModel.xpathQuery(`//iframe[@id="${frameId}"]`);
if (!nodes.length) {
throw new errors.NoSuchFrameError();
}
this.appModel.activateFrame(nodes[0]);
/**
* Set the active frame
*
* @param {number} frameId
* @returns {Promise<void>}
* @this {FakeDriver}
*/
async setFrame(frameId) {
this.assertWebviewContext();
if (frameId === null) {
this.appModel.deactivateFrame();
} else {
let nodes = this.appModel.xpathQuery(`//iframe[@id="${frameId}"]`);
if (!nodes.length) {
throw new errors.NoSuchFrameError();
}
this.appModel.activateFrame(nodes[0]);
}
}
return ContextsCommands;
}
},
};
/**
* @typedef {import('../driver').FakeDriverCore} FakeDriverCore
* @typedef {import('../types').IContextsCommands} IContextsCommands
*/
/**
* @template T,[U={}],[V=Array<any>]
* @typedef {import('@appium/types').Class<T,U,V>} Class
* @typedef {import('../driver').FakeDriver} FakeDriver
*/
+136 -95
View File
@@ -1,120 +1,161 @@
import _ from 'lodash';
import {errors} from 'appium/driver';
/**
* @template {Class<import('../types').IContextsCommands & import('../types').IAlertCommands>} T
* @param {T} Base
*/
export function ElementMixin(Base) {
export default {
/**
* @implements {IElementCommands}
* @this {FakeDriver}
*/
class ElementCommands extends Base {
getElements(elIds) {
for (let elId of elIds) {
if (!_.has(this.elMap, elId)) {
throw new errors.StaleElementReferenceError();
}
getElements(elIds) {
for (let elId of elIds) {
if (!_.has(this.elMap, elId)) {
throw new errors.StaleElementReferenceError();
}
return elIds.map((e) => this.elMap[e]);
}
return elIds.map((e) => this.elMap[e]);
},
getElement(elId) {
return this.getElements([elId])[0];
}
/**
* @this {FakeDriver}
*/
getElement(elId) {
return this.getElements([elId])[0];
},
async getName(elementId) {
let el = this.getElement(elementId);
return el.tagName;
}
/**
* @this {FakeDriver}
*/
async getName(elementId) {
let el = this.getElement(elementId);
return el.tagName;
},
async elementDisplayed(elementId) {
let el = this.getElement(elementId);
return el.isVisible();
}
/**
* @this {FakeDriver}
*/
async elementDisplayed(elementId) {
let el = this.getElement(elementId);
return el.isVisible();
},
async elementEnabled(elementId) {
let el = this.getElement(elementId);
return el.isEnabled();
}
/**
* @this {FakeDriver}
*/
async elementEnabled(elementId) {
let el = this.getElement(elementId);
return el.isEnabled();
},
async elementSelected(elementId) {
let el = this.getElement(elementId);
return el.isSelected();
}
/**
* @this {FakeDriver}
*/
async elementSelected(elementId) {
let el = this.getElement(elementId);
return el.isSelected();
},
async setValue(keys, elementId) {
let value = keys;
if (keys instanceof Array) {
value = keys.join('');
}
let el = this.getElement(elementId);
if (el.type !== 'MockInputField') {
throw new errors.InvalidElementStateError();
}
el.setAttr('value', value);
/**
* @this {FakeDriver}
*/
async setValue(keys, elementId) {
let value = keys;
if (keys instanceof Array) {
value = keys.join('');
}
let el = this.getElement(elementId);
if (el.type !== 'MockInputField') {
throw new errors.InvalidElementStateError();
}
el.setAttr('value', value);
},
async getText(elementId) {
let el = this.getElement(elementId);
return el.getAttr('value');
}
/**
* @this {FakeDriver}
*/
async getText(elementId) {
let el = this.getElement(elementId);
return el.getAttr('value');
},
async clear(elementId) {
await this.setValue('', elementId);
}
/**
* @this {FakeDriver}
*/
async clear(elementId) {
await this.setValue('', elementId);
},
/**
* This comment should be displayed instead of the one from ExternalDriver
* @param {string} elementId
*/
async click(elementId) {
this.assertNoAlert();
let el = this.getElement(elementId);
if (!el.isVisible()) {
throw new errors.InvalidElementStateError();
}
el.click();
this.focusedElId = elementId;
/**
* This comment should be displayed instead of the one from ExternalDriver
* @param {string} elementId
* @this {FakeDriver}
*/
async click(elementId) {
this.assertNoAlert();
let el = this.getElement(elementId);
if (!el.isVisible()) {
throw new errors.InvalidElementStateError();
}
el.click();
this.focusedElId = elementId;
},
async getAttribute(attr, elementId) {
let el = this.getElement(elementId);
return el.getAttr(attr);
}
getElementRect(elementId) {
let el = this.getElement(elementId);
return el.getElementRect();
}
getSize(elementId) {
let el = this.getElement(elementId);
return el.getSize();
}
/**
* @this {FakeDriver}
*/
async getAttribute(attr, elementId) {
let el = this.getElement(elementId);
return el.getAttr(attr);
},
equalsElement(el1Id, el2Id) {
let el1 = this.getElement(el1Id);
let el2 = this.getElement(el2Id);
return el1.equals(el2);
}
/**
* @this {FakeDriver}
*/
getElementRect(elementId) {
let el = this.getElement(elementId);
return el.getElementRect();
},
async getCssProperty(prop, elementId) {
this.assertWebviewContext();
let el = this.getElement(elementId);
return el.getCss(prop);
}
/**
* @this {FakeDriver}
*/
getSize(elementId) {
let el = this.getElement(elementId);
return el.getSize();
},
getLocationInView = this.getLocation;
}
/**
* @this {FakeDriver}
*/
equalsElement(el1Id, el2Id) {
let el1 = this.getElement(el1Id);
let el2 = this.getElement(el2Id);
return el1.equals(el2);
},
return ElementCommands;
}
/**
* @this {FakeDriver}
*/
async getCssProperty(prop, elementId) {
this.assertWebviewContext();
let el = this.getElement(elementId);
return el.getCss(prop);
},
/**
* @param {string} elementId
* @this {FakeDriver}
*/
async getLocation(elementId) {
const el = this.getElement(elementId);
return el.getLocation();
},
/**
* @this {FakeDriver}
*/
async getLocationInView(elementId) {
return this.getLocation(elementId);
},
};
/**
* @typedef {import('../driver').FakeDriverCore} FakeDriverCore
* @typedef {import('../types').IElementCommands} IElementCommands
*/
/**
* @template T,[U={}],[V=Array<any>]
* @typedef {import('@appium/types').Class<T,U,V>} Class
* @typedef {import('../driver').FakeDriver} FakeDriver
*/
+94 -98
View File
@@ -2,121 +2,117 @@ import _ from 'lodash';
import {errors} from 'appium/driver';
import {FakeElement} from '../fake-element';
/**
* @template {Class<import('../types').IElementCommands>} T
* @param {T} Base
*/
export function FindMixin(Base) {
export default {
/**
* @implements {IFindCommands}
* @this {FakeDriver}
*/
class FindCommands extends Base {
getExistingElementForNode(node) {
for (let [id, el] of _.toPairs(this.elMap)) {
if (el.node === node) {
return id;
}
getExistingElementForNode(node) {
for (let [id, el] of _.toPairs(this.elMap)) {
if (el.node === node) {
return id;
}
return null;
}
return null;
},
/**
* @this {FakeDriver}
*/
wrapNewEl(obj) {
// first check and see if we already have a ref to this element
let existingElId = this.getExistingElementForNode(obj);
if (existingElId) {
return {ELEMENT: existingElId};
}
wrapNewEl(obj) {
// first check and see if we already have a ref to this element
let existingElId = this.getExistingElementForNode(obj);
if (existingElId) {
return {ELEMENT: existingElId};
}
// otherwise add the element to the map
this.maxElId++;
this.elMap[this.maxElId.toString()] = new FakeElement(obj, this.appModel);
return {ELEMENT: this.maxElId.toString()};
},
// otherwise add the element to the map
this.maxElId++;
this.elMap[this.maxElId.toString()] = new FakeElement(obj, this.appModel);
return {ELEMENT: this.maxElId.toString()};
/**
* @template {boolean} Mult
* @template [Ctx=any]
* @param {string} strategy
* @param {string} selector
* @param {Mult} mult
* @param {Ctx} [context]
* @returns {Promise<Mult extends true ? Element[] : Element>}
* @this {FakeDriver}
*/
async findElOrEls(strategy, selector, mult, context) {
let qMap = {
xpath: 'xpathQuery',
id: 'idQuery',
'accessibility id': 'idQuery',
'class name': 'classQuery',
'tag name': 'classQuery',
'css selector': 'cssQuery',
};
// TODO this error checking should probably be part of MJSONWP?
if (!_.includes(_.keys(qMap), strategy)) {
throw new errors.UnknownCommandError();
}
/**
* @template {boolean} Mult
* @template [Ctx=any]
* @param {string} strategy
* @param {string} selector
* @param {Mult} mult
* @param {Ctx} [context]
* @returns {Promise<Mult extends true ? Element[] : Element>}
*/
async findElOrEls(strategy, selector, mult, context) {
let qMap = {
xpath: 'xpathQuery',
id: 'idQuery',
'accessibility id': 'idQuery',
'class name': 'classQuery',
'tag name': 'classQuery',
'css selector': 'cssQuery',
};
// 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();
}
let els = this.appModel[qMap[strategy]](selector, context);
if (selector === 'badsel') {
throw new errors.InvalidSelectorError();
}
let els = this.appModel[qMap[strategy]](selector, context);
let retval;
if (els.length) {
if (mult) {
let allEls = [];
for (let el of els) {
allEls.push(this.wrapNewEl(el));
}
retval = allEls;
} else {
retval = this.wrapNewEl(els[0]);
let retval;
if (els.length) {
if (mult) {
let allEls = [];
for (let el of els) {
allEls.push(this.wrapNewEl(el));
}
} else if (mult) {
retval = [];
retval = allEls;
} else {
throw new errors.NoSuchElementError();
retval = this.wrapNewEl(els[0]);
}
return /** @type {Mult extends true ? Element[] : Element} */ (retval);
} else if (mult) {
retval = [];
} else {
throw new errors.NoSuchElementError();
}
return /** @type {Mult extends true ? Element[] : Element} */ (retval);
},
/**
* This should override whatever's in ExternalDriver
* @param {string} strategy Strategy
* @param {string} selector Selector
*/
async findElement(strategy, selector) {
return this.findElOrEls(strategy, selector, false);
}
/**
* This should override whatever's in ExternalDriver
* @param {string} strategy Strategy
* @param {string} selector Selector
* @this {FakeDriver}
*/
async findElement(strategy, selector) {
return this.findElOrEls(strategy, selector, false);
},
async findElements(strategy, selector) {
return this.findElOrEls(strategy, selector, true);
}
/**
* @this {FakeDriver}
*/
async findElements(strategy, selector) {
return this.findElOrEls(strategy, selector, true);
},
async findElementFromElement(strategy, selector, elementId) {
let el = this.getElement(elementId);
return this.findElOrEls(strategy, selector, false, el.xmlFragment);
}
/**
* @this {FakeDriver}
*/
async findElementFromElement(strategy, selector, elementId) {
let el = this.getElement(elementId);
return this.findElOrEls(strategy, selector, false, el.xmlFragment);
},
async findElementsFromElement(strategy, selector, elementId) {
let el = this.getElement(elementId);
return this.findElOrEls(strategy, selector, true, el.xmlFragment);
}
}
return FindCommands;
}
/**
* @this {FakeDriver}
*/
async findElementsFromElement(strategy, selector, elementId) {
let el = this.getElement(elementId);
return this.findElOrEls(strategy, selector, true, el.xmlFragment);
},
};
/**
* @typedef {import('../driver').FakeDriverCore} FakeDriverCore
* @typedef {import('@appium/types').Element} Element
*/
/**
* @template T,[U={}],[V=Array<any>]
* @typedef {import('@appium/types').Class<T,U,V>} Class
*/
/**
* @template [Ctx=any]
* @typedef {import('@appium/types').IFindCommands<Ctx>} IFindCommands
* @typedef {import('../driver').FakeDriver} FakeDriver
*/
+129 -101
View File
@@ -2,118 +2,146 @@ import {errors} from 'appium/driver';
const ORIENTATIONS = new Set(['LANDSCAPE', 'PORTRAIT']);
/**
* @template {Class<import('../types').IContextsCommands & import('../types').IElementCommands>} T
* @param {T} Base
*/
export function GeneralMixin(Base) {
export default {
/**
* @implements {IGeneralCommands}
* @this {FakeDriver}
*/
class GeneralCommands extends Base {
async title() {
this.assertWebviewContext();
return this.appModel.title;
async title() {
this.assertWebviewContext();
return this.appModel.title;
},
/**
* @this {FakeDriver}
*/
async keys(value) {
if (!this.focusedElId) {
throw new errors.InvalidElementStateError();
}
await this.setValue(value, this.focusedElId);
},
async keys(value) {
if (!this.focusedElId) {
throw new errors.InvalidElementStateError();
}
await this.setValue(value, this.focusedElId);
/**
* @this {FakeDriver}
*/
async setGeoLocation(location) {
// TODO test this adequately once WD bug is fixed
this.appModel.lat = location.latitude;
this.appModel.long = location.longitude;
},
/**
* @this {FakeDriver}
*/
async getGeoLocation() {
return this.appModel.currentGeoLocation;
},
/**
* @this {FakeDriver}
*/
async getPageSource() {
return this.appModel.rawXml;
},
/**
* @this {FakeDriver}
*/
async getOrientation() {
return this.appModel.orientation;
},
/**
*
* @param {import('../types').FakeDriverCaps['orientation']} o
* @this {FakeDriver}
*/
async setOrientation(o) {
if (!ORIENTATIONS.has(o)) {
throw new errors.UnknownError('Orientation must be LANDSCAPE or PORTRAIT');
}
this.appModel.orientation = o;
},
async setGeoLocation(location) {
// TODO test this adequately once WD bug is fixed
this.appModel.lat = location.latitude;
this.appModel.long = location.longitude;
/**
* @this {FakeDriver}
*/
async getScreenshot() {
return this.appModel.getScreenshot();
},
/**
* @this {FakeDriver}
*/
async getWindowSize() {
return {width: this.appModel.width, height: this.appModel.height};
},
/**
* @this {FakeDriver}
*/
async getWindowRect() {
return {width: this.appModel.width, height: this.appModel.height, x: 0, y: 0};
},
/**
*
* @this {FakeDriver}
*/
async performActions(actions) {
this.appModel.actionLog.push(actions);
},
/**
* @this {FakeDriver}
*/
async releaseActions() {},
/**
* @this {FakeDriver}
*/
async getLog(type) {
switch (type) {
case 'actions':
return this.appModel.actionLog;
default:
throw new Error(`Don't understand log type '${type}'`);
}
},
async getGeoLocation() {
return this.appModel.currentGeoLocation;
}
/**
* @this {FakeDriver}
*/
async mobileShake() {
this.shook = true;
},
async getPageSource() {
return this.appModel.rawXml;
}
/**
* @this {FakeDriver}
*/
async doubleClick() {},
async getOrientation() {
return this.appModel.orientation;
}
/**
* @this {FakeDriver}
*/
async execute(script, args) {
return await this.executeMethod(script, args);
},
/**
*
* @param {import('../types').FakeDriverCaps['orientation']} o
*/
async setOrientation(o) {
if (!ORIENTATIONS.has(o)) {
throw new errors.UnknownError('Orientation must be LANDSCAPE or PORTRAIT');
}
this.appModel.orientation = o;
}
async getScreenshot() {
return this.appModel.getScreenshot();
}
async getWindowSize() {
return {width: this.appModel.width, height: this.appModel.height};
}
async getWindowRect() {
return {width: this.appModel.width, height: this.appModel.height, x: 0, y: 0};
}
async performActions(actions) {
this.appModel.actionLog.push(actions);
}
async releaseActions() {}
async getLog(type) {
switch (type) {
case 'actions':
return this.appModel.actionLog;
default:
throw new Error(`Don't understand log type '${type}'`);
}
}
async mobileShake() {
this.shook = true;
}
async doubleClick() {}
async execute(script, args) {
return await this.executeMethod(script, args);
}
/**
* Add two or maybe even three numbers
*
* @param {number} num1
* @param {number} num2
* @param {number} [num3]
* @returns {Promise<number>}
*/
async fakeAddition(num1, num2, num3 = 0) {
return num1 + num2 + (num3 ?? 0);
}
}
return GeneralCommands;
}
/**
* Add two or maybe even three numbers
*
* @param {number} num1
* @param {number} num2
* @param {number} [num3]
* @returns {Promise<number>}
* @this {FakeDriver}
*/
async fakeAddition(num1, num2, num3 = 0) {
return num1 + num2 + (num3 ?? 0);
},
};
/**
* @typedef {import('../driver').FakeDriverCore} FakeDriverCore
*/
/**
* @template T,[U={}],[V=Array<any>]
* @typedef {import('@appium/types').Class<T,U,V>} Class
*/
/**
* @typedef {import('../types').IGeneralCommands} IGeneralCommands
* @typedef {import('../driver').FakeDriver} FakeDriver
*/
+5 -13
View File
@@ -1,16 +1,8 @@
import {AlertMixin} from './alert';
import {ContextsMixin} from './contexts';
import {ElementMixin} from './element';
import {FindMixin} from './find';
import {GeneralMixin} from './general';
/**
*
* @param {import('@appium/types').Class<import('../driver').FakeDriverCore>} Base
*/
export function FakeDriverMixin(Base) {
return GeneralMixin(FindMixin(ElementMixin(AlertMixin(ContextsMixin(Base)))));
}
export {default as alert} from './alert';
export {default as contexts} from './contexts';
export {default as element} from './element';
export {default as find} from './find';
export {default as general} from './general';
/* // TODO:
//rest.post('/wd/hub/session/:sessionId?/touch/click', controller.doClick);
+76 -20
View File
@@ -2,7 +2,7 @@ import B from 'bluebird';
import {BaseDriver, errors} from 'appium/driver';
import {deprecatedCommandsLogged} from '@appium/base-driver/build/lib/protocol/protocol';
import {FakeApp} from './fake-app';
import {FakeDriverMixin} from './commands';
import {alert, contexts, element, find, general} from './commands';
const FAKE_DRIVER_CONSTRAINTS = /** @type {const} */ ({
app: {
@@ -22,7 +22,7 @@ const FAKE_DRIVER_CONSTRAINTS = /** @type {const} */ ({
* @extends {BaseDriver<FakeDriverConstraints>}
* @implements {ExternalDriver<FakeDriverConstraints>}
*/
export class FakeDriverCore extends BaseDriver {
export class FakeDriver extends BaseDriver {
desiredCapConstraints = FAKE_DRIVER_CONSTRAINTS;
/** @type {string} */
@@ -190,36 +190,92 @@ export class FakeDriverCore extends BaseDriver {
},
});
/**
* Add two or maybe even three numbers
*
* @param {number} num1
* @param {number} num2
* @param {number} [num3]
* @returns {Promise<number>}
*/
// eslint-disable-next-line no-unused-vars
async fakeAddition(num1, num2, num3 = 0) {
throw new errors.NotImplementedError();
}
static fakeRoute(req, res) {
res.send(JSON.stringify({fakedriver: 'fakeResponse'}));
}
static async updateServer(expressApp, httpServer, cliArgs) {
// eslint-disable-line require-await
expressApp.all('/fakedriver', FakeDriverCore.fakeRoute);
expressApp.all('/fakedriver', FakeDriver.fakeRoute);
expressApp.all('/fakedriverCliArgs', (req, res) => {
res.send(JSON.stringify(cliArgs));
});
}
/*********
* ALERT *
*********/
assertNoAlert = alert.assertNoAlert;
assertAlert = alert.assertAlert;
getAlertText = alert.getAlertText;
setAlertText = alert.setAlertText;
postAcceptAlert = alert.postAcceptAlert;
postDismissAlert = alert.postDismissAlert;
/************
* CONTEXTS *
************/
getRawContexts = contexts.getRawContexts;
assertWebviewContext = contexts.assertWebviewContext;
getCurrentContext = contexts.getCurrentContext;
getContexts = contexts.getContexts;
setContext = contexts.setContext;
setFrame = contexts.setFrame;
/************
* ELEMENTS *
************/
getElements = element.getElements;
getElement = element.getElement;
getName = element.getName;
elementDisplayed = element.elementDisplayed;
elementEnabled = element.elementEnabled;
elementSelected = element.elementSelected;
setValue = element.setValue;
getText = element.getText;
clear = element.clear;
click = element.click;
getAttribute = element.getAttribute;
getElementRect = element.getElementRect;
getSize = element.getSize;
equalsElement = element.equalsElement;
getCssProperty = element.getCssProperty;
getLocation = element.getLocation;
getLocationInView = element.getLocationInView;
/********
* FIND *
********/
getExistingElementForNode = find.getExistingElementForNode;
wrapNewEl = find.wrapNewEl;
findElOrEls = find.findElOrEls;
findElement = find.findElement;
findElements = find.findElements;
findElementFromElement = find.findElementFromElement;
findElementsFromElement = find.findElementsFromElement;
/***********
* GENERAL *
***********/
title = general.title;
keys = general.keys;
setGeoLocation = general.setGeoLocation;
getGeoLocation = general.getGeoLocation;
getPageSource = general.getPageSource;
getOrientation = general.getOrientation;
setOrientation = general.setOrientation;
getScreenshot = general.getScreenshot;
getWindowSize = general.getWindowSize;
getWindowRect = general.getWindowRect;
performActions = general.performActions;
getLog = general.getLog;
mobileShake = general.mobileShake;
doubleClick = general.doubleClick;
execute = general.execute;
fakeAddition = general.fakeAddition;
releaseActions = general.releaseActions;
}
/**
* @extends FakeDriverCore
*/
export class FakeDriver extends FakeDriverMixin(FakeDriverCore) {}
export default FakeDriver;
/**
+1 -29
View File
@@ -1,7 +1,5 @@
import type {DriverCaps, ExternalDriver, W3CDriverCaps} from '@appium/types';
import type {DriverCaps, W3CDriverCaps} from '@appium/types';
import type {FakeDriverConstraints} from './driver';
import {FakeApp} from './fake-app';
import {FakeElement} from './fake-element';
/**
* W3C-style caps for {@link FakeDriver}
@@ -14,29 +12,3 @@ export type W3CFakeDriverCaps = W3CDriverCaps<FakeDriverConstraints>;
* @public
*/
export type FakeDriverCaps = DriverCaps<FakeDriverConstraints>;
export interface IFakeDriver extends ExternalDriver<FakeDriverConstraints> {
elMap: Record<string, FakeElement>;
maxElId: number;
appModel: FakeApp;
focusedElId: string;
curContext: string;
}
export interface IGeneralCommands extends IFakeDriver {
fakeAddition(num1: number, num2: number, num3?: number): Promise<number>;
}
export interface IContextsCommands extends IFakeDriver {
assertWebviewContext(): void;
}
export interface IElementCommands extends IFakeDriver {
getElement(id: string): FakeElement;
getElements(ids: string[]): FakeElement[];
setValue(text: string, id: string): Promise<void>;
}
export interface IAlertCommands extends IFakeDriver {
assertNoAlert(): void;
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/fake-driver",
"version": "5.1.2",
"version": "5.1.4",
"description": "Mock driver used internally by Appium for testing. Ignore",
"keywords": [
"automation",
@@ -81,5 +81,5 @@
"entryPoint": "./lib/index.js"
},
"types": "./build/lib/index.d.ts",
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd"
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72"
}
+7 -17
View File
@@ -1,23 +1,13 @@
import _ from 'lodash';
import contextCommands from '../../lib/commands/contexts';
import elementCommands from '../../lib/commands/element';
import findCommands from '../../lib/commands/find';
import generalCommands from '../../lib/commands/general';
import exportedCommands from '../../lib/commands';
import * as commands from '../../lib/commands';
import {FakeDriver} from '../../lib/driver';
describe('Driver commands', function () {
let allCommands = [
_.keys(contextCommands),
_.keys(elementCommands),
_.keys(findCommands),
_.keys(generalCommands),
];
let totalCommands = _.sum(allCommands.map((c) => c.length));
it('should not overlap between files', function () {
_.union(...allCommands).length.should.equal(totalCommands);
});
it('should export all commands and not leave any out', function () {
_.difference(_.union(...allCommands), _.keys(exportedCommands)).should.eql([]);
const allCommands = Object.values(commands).map(Object.keys).flat();
it('should import all commands and not leave any out', function () {
const driver = new FakeDriver();
_.difference(allCommands, Object.keys(driver)).should.be.empty;
});
});
+16
View File
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.1.4](https://github.com/appium/appium/compare/@appium/fake-plugin@3.1.3...@appium/fake-plugin@3.1.4) (2023-01-23)
**Note:** Version bump only for package @appium/fake-plugin
## [3.1.3](https://github.com/appium/appium/compare/@appium/fake-plugin@3.1.2...@appium/fake-plugin@3.1.3) (2023-01-13)
**Note:** Version bump only for package @appium/fake-plugin
## [3.1.2](https://github.com/appium/appium/compare/@appium/fake-plugin@3.1.1...@appium/fake-plugin@3.1.2) (2023-01-13)
**Note:** Version bump only for package @appium/fake-plugin
+33 -4
View File
@@ -5,10 +5,7 @@ import {BasePlugin} from 'appium/plugin';
import B from 'bluebird';
class FakePlugin extends BasePlugin {
async getFakePluginArgs() {
await B.delay(1);
return this.cliArgs;
}
fakeThing = 'PLUGIN_FAKE_THING';
static newMethodMap = /** @type {const} */ ({
'/session/:sessionId/fake_data': {
@@ -27,6 +24,19 @@ class FakePlugin extends BasePlugin {
/** @type {string?} */
static _unexpectedData = null;
static executeMethodMap = /** @type {const} */ ({
// this execute method overrides fake-drivers fake: getThing, for testing
'fake: getThing': {
command: 'getFakeThing',
},
// this is a totally new execute method
'fake: plugMeIn': {
command: 'plugMeIn',
params: {required: ['socket']},
},
});
static fakeRoute(req, res) {
res.send(JSON.stringify({fake: 'fakeResponse'}));
}
@@ -45,6 +55,21 @@ class FakePlugin extends BasePlugin {
});
}
async getFakeThing() {
await B.delay(1);
return this.fakeThing;
}
async plugMeIn(next, driver, /** @type {string} */ socket) {
await B.delay(1);
return `Plugged in to ${socket}`;
}
async getFakePluginArgs() {
await B.delay(1);
return this.cliArgs;
}
async getPageSource(next, driver, ...args) {
await B.delay(10);
return `<Fake>${JSON.stringify(args)}</Fake>`;
@@ -78,6 +103,10 @@ class FakePlugin extends BasePlugin {
async onUnexpectedShutdown(driver, cause) {
FakePlugin._unexpectedData = `Session ended because ${cause}`;
}
async execute(next, driver, script, args) {
return await this.executeMethod(next, driver, script, args);
}
}
export {FakePlugin};
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/fake-plugin",
"version": "3.1.2",
"version": "3.1.4",
"description": "A fake Appium 2.0 plugin",
"keywords": [
"automation",
@@ -38,8 +38,8 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/base-plugin": "^2.1.2",
"@appium/support": "^3.1.2",
"@appium/base-plugin": "^2.2.0",
"@appium/support": "^3.1.4",
"@types/bluebird": "3.5.38",
"bluebird": "3.7.2",
"lodash": "4.17.21",
@@ -63,7 +63,7 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd",
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72",
"tags": [
"appium"
],
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.0.5](https://github.com/appium/appium/compare/@appium/images-plugin@2.0.4...@appium/images-plugin@2.0.5) (2023-01-13)
**Note:** Version bump only for package @appium/images-plugin
## [2.0.4](https://github.com/appium/appium/compare/@appium/images-plugin@2.0.3...@appium/images-plugin@2.0.4) (2023-01-13)
**Note:** Version bump only for package @appium/images-plugin
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/images-plugin",
"version": "2.0.4",
"version": "2.0.5",
"description": "Plugin for working with images and image elements in Appium",
"keywords": [
"automation",
@@ -38,7 +38,7 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/opencv": "^2.0.4",
"@appium/opencv": "^2.0.5",
"lodash": "4.17.21",
"lru-cache": "7.14.1",
"source-map-support": "0.5.21"
@@ -57,7 +57,7 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd",
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72",
"typedoc": {
"entryPoint": "./lib/plugin.js"
}
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.0.5](https://github.com/appium/appium/compare/@appium/opencv@2.0.4...@appium/opencv@2.0.5) (2023-01-13)
**Note:** Version bump only for package @appium/opencv
## [2.0.4](https://github.com/appium/appium/compare/@appium/opencv@2.0.3...@appium/opencv@2.0.4) (2023-01-13)
**Note:** Version bump only for package @appium/opencv
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/opencv",
"version": "2.0.4",
"version": "2.0.5",
"description": "OpenCV-related helper library",
"keywords": [
"automation",
@@ -54,7 +54,7 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd",
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72",
"overrides": {
"jpeg-js": "0.4.4"
}
+16
View File
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.3.6](https://github.com/appium/appium/compare/@appium/plugin-test-support@0.3.5...@appium/plugin-test-support@0.3.6) (2023-01-23)
**Note:** Version bump only for package @appium/plugin-test-support
## [0.3.5](https://github.com/appium/appium/compare/@appium/plugin-test-support@0.3.4...@appium/plugin-test-support@0.3.5) (2023-01-13)
**Note:** Version bump only for package @appium/plugin-test-support
## [0.3.4](https://github.com/appium/appium/compare/@appium/plugin-test-support@0.3.3...@appium/plugin-test-support@0.3.4) (2023-01-13)
**Note:** Version bump only for package @appium/plugin-test-support
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/plugin-test-support",
"version": "0.3.4",
"version": "0.3.6",
"description": "Testing utilities for Appium plugins",
"keywords": [
"automation",
@@ -40,7 +40,7 @@
"test:unit": "exit 0"
},
"dependencies": {
"@appium/types": "^0.8.2",
"@appium/types": "^0.9.0",
"get-port": "5.1.1",
"log-symbols": "4.1.0",
"source-map-support": "0.5.21",
@@ -57,5 +57,5 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd"
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72"
}
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.0.4](https://github.com/appium/appium/compare/@appium/relaxed-caps-plugin@1.0.3...@appium/relaxed-caps-plugin@1.0.4) (2023-01-13)
**Note:** Version bump only for package @appium/relaxed-caps-plugin
## [1.0.3](https://github.com/appium/appium/compare/@appium/relaxed-caps-plugin@1.0.2...@appium/relaxed-caps-plugin@1.0.3) (2023-01-13)
**Note:** Version bump only for package @appium/relaxed-caps-plugin
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/relaxed-caps-plugin",
"version": "1.0.3",
"version": "1.0.4",
"description": "An Appium 2.0 plugin that loosens requirements for vendor prefixes on caps",
"keywords": [
"automation",
@@ -56,7 +56,7 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd",
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72",
"tags": [
"appium"
],
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.2.3](https://github.com/appium/appium/compare/@appium/schema@0.2.2...@appium/schema@0.2.3) (2023-01-13)
**Note:** Version bump only for package @appium/schema
## [0.2.2](https://github.com/appium/appium/compare/@appium/schema@0.2.1...@appium/schema@0.2.2) (2023-01-13)
**Note:** Version bump only for package @appium/schema
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/schema",
"version": "0.2.2",
"version": "0.2.3",
"description": "Appium Configuration Schema",
"keywords": [
"automation",
@@ -50,5 +50,5 @@
"typedoc": {
"entryPoint": "./lib/index.js"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd"
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72"
}
+22
View File
@@ -3,6 +3,28 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.1.4](https://github.com/appium/appium/compare/@appium/support@3.1.3...@appium/support@3.1.4) (2023-01-23)
### Bug Fixes
* **support:** update dependency @types/glob to v8.0.1 ([854c5ec](https://github.com/appium/appium/commit/854c5ec9467a14e9ed7c5b18538413250a615716))
* **support:** update dependency glob to v8.1.0 ([d7b35ab](https://github.com/appium/appium/commit/d7b35ab28b8afd0f93f775a223373956a57ee881))
* **types:** update dependency type-fest to v3.5.2 ([64fd8ce](https://github.com/appium/appium/commit/64fd8ce94018b0bb7ccb2baade8d525703f41c45))
* **types:** update dependency type-fest to v3.5.3 ([6c4ba8c](https://github.com/appium/appium/commit/6c4ba8caa508840640f05eea1ab41ecb290312aa))
## [3.1.3](https://github.com/appium/appium/compare/@appium/support@3.1.2...@appium/support@3.1.3) (2023-01-13)
**Note:** Version bump only for package @appium/support
## [3.1.2](https://github.com/appium/appium/compare/@appium/support@3.1.1...@appium/support@3.1.2) (2023-01-13)
**Note:** Version bump only for package @appium/support
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/support",
"version": "3.1.2",
"version": "3.1.4",
"description": "Support libs used across appium packages",
"keywords": [
"automation",
@@ -40,13 +40,13 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/tsconfig": "^0.2.2",
"@appium/types": "^0.8.2",
"@appium/tsconfig": "^0.2.3",
"@appium/types": "^0.9.0",
"@colors/colors": "1.5.0",
"@types/archiver": "5.3.1",
"@types/base64-stream": "1.0.2",
"@types/find-root": "1.1.2",
"@types/glob": "8.0.0",
"@types/glob": "8.0.1",
"@types/jsftp": "2.1.2",
"@types/klaw": "3.0.3",
"@types/lockfile": "1.0.2",
@@ -69,7 +69,7 @@
"bplist-parser": "0.3.2",
"form-data": "4.0.0",
"get-stream": "6.0.1",
"glob": "8.0.3",
"glob": "8.1.0",
"jimp": "0.16.2",
"jsftp": "2.1.3",
"klaw": "4.1.0",
@@ -94,7 +94,7 @@
"source-map-support": "0.5.21",
"supports-color": "8.1.1",
"teen_process": "2.0.2",
"type-fest": "3.5.1",
"type-fest": "3.5.3",
"uuid": "9.0.0",
"which": "3.0.0",
"yauzl": "2.10.0"
@@ -106,7 +106,7 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd",
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72",
"typedoc": {
"entryPoint": "./lib/index.js"
},
+16
View File
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.0.6](https://github.com/appium/appium/compare/@appium/test-support@3.0.5...@appium/test-support@3.0.6) (2023-01-23)
**Note:** Version bump only for package @appium/test-support
## [3.0.5](https://github.com/appium/appium/compare/@appium/test-support@3.0.4...@appium/test-support@3.0.5) (2023-01-13)
**Note:** Version bump only for package @appium/test-support
## [3.0.4](https://github.com/appium/appium/compare/@appium/test-support@3.0.3...@appium/test-support@3.0.4) (2023-01-13)
**Note:** Version bump only for package @appium/test-support
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/test-support",
"version": "3.0.4",
"version": "3.0.6",
"description": "A collection of test utilities used across Appium packages",
"keywords": [
"automation",
@@ -44,7 +44,7 @@
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/support": "^3.1.2",
"@appium/support": "^3.1.4",
"@colors/colors": "1.5.0",
"bluebird": "3.7.2",
"lodash": "4.17.21",
@@ -59,5 +59,5 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd"
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72"
}
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.2.3](https://github.com/appium/appium/compare/@appium/tsconfig@0.2.2...@appium/tsconfig@0.2.3) (2023-01-13)
**Note:** Version bump only for package @appium/tsconfig
## [0.2.2](https://github.com/appium/appium/compare/@appium/tsconfig@0.2.1...@appium/tsconfig@0.2.2) (2023-01-13)
**Note:** Version bump only for package @appium/tsconfig
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/tsconfig",
"version": "0.2.2",
"version": "0.2.3",
"description": "Shared TypeScript Config for Appium",
"main": "tsconfig.json",
"keywords": [
@@ -35,5 +35,5 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd"
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72"
}
@@ -3,6 +3,29 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [0.3.4](https://github.com/appium/appium/compare/@appium/typedoc-plugin-appium@0.3.3...@appium/typedoc-plugin-appium@0.3.4) (2023-01-23)
### Bug Fixes
* **typedoc-plugin-appium:** fix keywords for typedoc plugin autodetection ([ed1edab](https://github.com/appium/appium/commit/ed1edab2098eed8f36a23419a2cc91c699756ed7))
* **typedoc-plugin-appium:** non-appium theme should not cause a fatal error ([ec48c9c](https://github.com/appium/appium/commit/ec48c9cea7949d5e05ab0f748265345d84007283))
* **typedoc-plugin-appium:** reduce severity of "missing method" error ([d0e1cb2](https://github.com/appium/appium/commit/d0e1cb2f65d5da11dff251e445861a3d74585bb6))
* **types:** update dependency type-fest to v3.5.2 ([64fd8ce](https://github.com/appium/appium/commit/64fd8ce94018b0bb7ccb2baade8d525703f41c45))
* **types:** update dependency type-fest to v3.5.3 ([6c4ba8c](https://github.com/appium/appium/commit/6c4ba8caa508840640f05eea1ab41ecb290312aa))
## [0.3.3](https://github.com/appium/appium/compare/@appium/typedoc-plugin-appium@0.3.2...@appium/typedoc-plugin-appium@0.3.3) (2023-01-13)
**Note:** Version bump only for package @appium/typedoc-plugin-appium
## [0.3.2](https://github.com/appium/appium/compare/@appium/typedoc-plugin-appium@0.3.1...@appium/typedoc-plugin-appium@0.3.2) (2023-01-13)
**Note:** Version bump only for package @appium/typedoc-plugin-appium
@@ -79,19 +79,13 @@ export function createExtensionReflection(
const parentCtx = ctx.withScope(extRefl);
const {routeMap: routeMap, execMethodDataSet: execCommandsData} = moduleCmds;
const sortedRouteMap = new Map([...routeMap].sort(([a], [b]) => a.localeCompare(b)));
for (const [route, commandSet] of sortedRouteMap) {
for (const [route, commandSet] of routeMap) {
for (const data of commandSet) {
createCommandReflection(log, parentCtx, data, extRefl, route);
}
}
// sort execute methods in alphabetical order by script
const sortedExecCommandsData = [...execCommandsData].sort((a, b) =>
a.script.localeCompare(b.script)
);
for (const data of sortedExecCommandsData) {
for (const data of execCommandsData) {
createCommandReflection(log, parentCtx, data, extRefl);
}
@@ -111,7 +111,7 @@ export function convertMethodMap({
const method = methods.get(command)?.method;
if (strict && !method) {
log.error('(%s) No method found for command "%s"', parentRefl.name, command);
log.warn('(%s) No method found for command "%s"; this is a bug', parentRefl.name, command);
continue;
}
@@ -12,7 +12,12 @@ import {
TupleType,
TypeOperatorType,
} from 'typedoc';
import {AllowedHttpMethod, ParentReflection} from '../model';
import {
AllowedHttpMethod,
AppiumPluginReflectionKind,
CommandReflection,
ParentReflection,
} from '../model';
import {NAME_EXTERNAL_DRIVER, NAME_TYPES_MODULE} from './builtin-external-driver';
import {NAME_BUILTIN_COMMAND_MODULE, NAME_METHOD_MAP} from './builtin-method-map';
import {NAME_NEW_METHOD_MAP, NAME_EXECUTE_METHOD_MAP, NAME_PARAMS} from './external';
@@ -21,7 +26,7 @@ type WithName<S extends string, R> = R & {
name: S;
};
type WithKind<K extends ReflectionKind, R> = R & {kind: K};
type WithKind<K extends ReflectionKind | AppiumPluginReflectionKind, R> = R & {kind: K};
/**
* Utility to narrow a declaration reflection to a specific `SomeType`
@@ -272,3 +277,11 @@ export type NonEmptyArray<T> = [T, ...T[]];
export type CallSignatureReflectionWithArity = CallSignatureReflection & {
parameters: NonEmptyArray<ParameterReflection>;
};
/**
* Can be used to narrow a {@linkcode CommandReflection} to one representing an execute method.
*/
export type ExecuteMethodCommandReflection = CommandReflection & {
kind: typeof AppiumPluginReflectionKind.ExecuteMethod;
script: string;
};
+1 -1
View File
@@ -58,7 +58,7 @@ export async function convert(app: Application): Promise<ConvertResult> {
// with TypeDoc
extensionReflections = createReflections(ctx, log, projectCommands);
} else {
log.error(`Appium theme disabled! Use "theme: 'appium'" in your typedoc.json`);
log.warn(`Appium theme disabled! Use "theme: 'appium'" in your typedoc.json`);
}
resolve({ctx, extensionReflections, projectCommands});
});
@@ -21,15 +21,3 @@ export enum AppiumPluginReflectionKind {
Extension = addReflectionKind('Extension', Driver | Plugin),
Any = addReflectionKind('Any', Command | ExecuteMethod | Driver | Plugin),
}
/**
* The values here are internally computed by TypeDoc, but we need to use them to filter on
* "groups" for display (since there's no direct relationship from a `ReflectionGroup` back to a `ReflectionKind`).
*/
export const AppiumPluginReflectionKindGroupTitles = new Set([
'Drivers',
'Plugins',
'Extensions',
'Execute methods',
'Commands',
]);
+10 -13
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/typedoc-plugin-appium",
"version": "0.3.2",
"version": "0.3.4",
"description": "TypeDoc plugin for Appium & its extensions",
"homepage": "https://appium.io",
"license": "Apache-2.0",
@@ -14,14 +14,11 @@
"directory": "packages/typedoc-plugin-appium"
},
"keywords": [
"automation",
"javascript",
"selenium",
"webdriver",
"ios",
"android",
"firefoxos",
"testing"
"typedoc-plugin",
"typedocplugin",
"typedoc-theme",
"appium",
"markdown"
],
"author": "https://github.com/appium",
"types": "./build/lib/index.d.ts",
@@ -29,9 +26,9 @@
"build": "cpy lib/theme/resources build",
"clean": "npx rimraf build/lib/theme/resources",
"test": "run-s test:unit",
"test:e2e": "exit 0",
"test:e2e": "mocha --timeout 20s \"test/e2e/**/*.e2e.spec.ts\"",
"test:smoke": "node ./index.js",
"test:unit": "mocha --no-timeout \"test/unit/**/*.spec.ts\""
"test:unit": "mocha --timeout 2s \"test/unit/**/*.spec.ts\""
},
"bugs": {
"url": "https://github.com/appium/appium/issues"
@@ -66,7 +63,7 @@
"handlebars": "4.7.7",
"lodash": "4.17.21",
"pluralize": "8.0.0",
"type-fest": "3.5.1"
"type-fest": "3.5.3"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd"
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72"
}
@@ -0,0 +1,28 @@
import {expect} from 'chai';
import {
KnownMethods,
BuiltinExternalDriverConverter,
NAME_TYPES_MODULE,
deriveComment,
} from '../../../lib/converter';
import {initConverter} from '../helpers';
describe('@appium/typedoc-plugin-appium', function () {
describe('deriveComment()', function () {
let knownMethods: KnownMethods;
before(async function () {
const converter = await initConverter(BuiltinExternalDriverConverter, NAME_TYPES_MODULE);
knownMethods = converter.convert();
expect(knownMethods.size).to.be.greaterThan(0);
expect(knownMethods.get('activateApp')!.comment).to.exist;
});
describe('when not provided a reflection nor `Comment` parameter', function () {
it('should derive the comment from KnownMethods', function () {
const commentData = deriveComment('activateApp', knownMethods);
expect(commentData).to.exist.and.to.have.keys('comment', 'commentSource');
});
});
});
});
@@ -12,7 +12,7 @@ import {initAppForPkgs, NAME_FAKE_DRIVER_MODULE} from '../helpers';
const {expect} = chai;
describe('@appium/typedoc-plugin-appium', function () {
describe('converter', function () {
describe('convertCommands()', function () {
let sandbox: SinonSandbox;
beforeEach(function () {
sandbox = createSandbox();
@@ -0,0 +1,143 @@
import {
Application,
Context,
DeclarationReflection,
ProjectReflection,
ReflectionKind,
TypeDocOptions,
} from 'typedoc';
import {convert, ConvertResult, postProcess, PostProcessResult, setup} from '../../lib';
import {
ExecuteMethodCommandReflection,
NAME_BUILTIN_COMMAND_MODULE,
NAME_TYPES_MODULE,
} from '../../lib/converter';
import {AppiumPluginReflectionKind, CommandReflection, ExtensionReflection} from '../../lib/model';
import {initAppForPkgs, NAME_FAKE_DRIVER_MODULE} from './helpers';
const {expect} = chai;
describe('@appium/typedoc-plugin-appium', function () {
/**
* Result of {@linkcode convert}
*/
let resolveBeginCtxPromise: Promise<ConvertResult>;
/**
* Result of {@linkcode postProcess}
*/
let resolveEndCtxPromise: Promise<PostProcessResult>;
/**
* Whatever {@linkcode Context} we're using to test
*/
let ctx: Context;
/**
* Array of {@linkcode ExtensionReflection} instances as in a {@linkcode ConvertResult}
*/
let extensionReflections!: ExtensionReflection[];
/**
* Creates a new TypeDoc application and/or resets it
*/
function reset({
entryPoints = [NAME_TYPES_MODULE, NAME_FAKE_DRIVER_MODULE, NAME_BUILTIN_COMMAND_MODULE],
...opts
}: Partial<TypeDocOptions> = {}): Application {
return setup(initAppForPkgs({entryPoints, ...opts}));
}
describe('convert()', function () {
describe('when "theme" is not "markdown" or "appium"', function () {
it('should do nothing', async function () {
const app = reset({theme: 'foo'});
resolveBeginCtxPromise = convert(app);
app.convert();
await expect(resolveBeginCtxPromise).to.eventually.not.have.all.keys(
'projectCommands',
'extensionReflections'
);
});
});
describe('when commands are found in the project', function () {
before(async function () {
const app = reset();
resolveBeginCtxPromise = convert(app);
app.convert();
const result = await resolveBeginCtxPromise;
extensionReflections = result.extensionReflections!;
});
it('should create CommandReflections for each extension', function () {
for (const extRefl of extensionReflections) {
const cmdRefls = extRefl.getChildrenByKind(AppiumPluginReflectionKind.Command as any);
expect(cmdRefls).to.not.be.empty;
}
});
});
describe('when no commands found in the project', function () {
it('should return an object without projectCommands and extensionReflections', async function () {
const app = reset({entryPoints: [NAME_TYPES_MODULE]});
resolveBeginCtxPromise = convert(app);
app.convert();
await expect(resolveBeginCtxPromise).to.eventually.not.have.all.keys(
'projectCommands',
'extensionReflections'
);
});
});
});
describe('postProcess()', function () {
let project: ProjectReflection;
let removed: Set<DeclarationReflection> | undefined;
describe('when the `outputModules` option is false', function () {
before(async function () {
const app = reset();
app.options.setValue('outputModules', false);
resolveBeginCtxPromise = convert(app);
resolveEndCtxPromise = postProcess(app);
app.convert();
[, {ctx, removed}] = await Promise.all([resolveBeginCtxPromise, resolveEndCtxPromise]);
({project} = ctx);
});
it('should mutate the project', function () {
const childRefls = project.getChildrenByKind(AppiumPluginReflectionKind.Extension as any);
expect(childRefls).to.have.lengthOf(project.children!.length).and.to.not.be.empty;
expect(project.getChildrenByKind(ReflectionKind.Module)).to.be.empty;
});
it('should remove DeclarationReflections', function () {
expect(removed).not.to.be.empty;
});
});
describe('when the `outputModules` option is true', function () {
before(async function () {
const app = reset();
app.options.setValue('outputModules', true);
resolveBeginCtxPromise = convert(app);
resolveEndCtxPromise = postProcess(app);
app.convert();
[, {ctx, removed}] = await Promise.all([resolveBeginCtxPromise, resolveEndCtxPromise]);
({project} = ctx);
});
it('should not remove anything from the project', function () {
const defaultRefls = project.getChildrenByKind(
~(AppiumPluginReflectionKind.Extension as any)
);
expect(defaultRefls).to.not.be.empty;
const pluginRefls = project.getChildrenByKind(AppiumPluginReflectionKind.Extension as any);
expect(pluginRefls).to.not.be.empty;
});
it('should not remove DeclarationReflections', function () {
expect(removed).to.be.undefined;
});
});
});
});
@@ -1,30 +0,0 @@
import {expect} from 'chai';
import {
KnownMethods,
BuiltinExternalDriverConverter,
NAME_TYPES_MODULE,
deriveComment,
} from '../../../lib/converter';
import {initConverter} from '../helpers';
describe('@appium/typedoc-plugin-appium', function () {
describe('comment', function () {
describe('deriveComment()', function () {
let knownMethods: KnownMethods;
before(async function () {
const converter = await initConverter(BuiltinExternalDriverConverter, NAME_TYPES_MODULE);
knownMethods = converter.convert();
expect(knownMethods.size).to.be.greaterThan(0);
expect(knownMethods.get('activateApp')!.comment).to.exist;
});
describe('when not provided a reflection nor `Comment` parameter', function () {
it('should derive the comment from KnownMethods', function () {
const commentData = deriveComment('activateApp', knownMethods);
expect(commentData).to.exist.and.to.have.keys('comment', 'commentSource');
});
});
});
});
});
@@ -1,170 +0,0 @@
import {
Application,
Context,
DeclarationReflection,
ProjectReflection,
ReflectionKind,
TypeDocOptions,
} from 'typedoc';
import {convert, ConvertResult, postProcess, PostProcessResult, setup} from '../../../lib';
import {NAME_BUILTIN_COMMAND_MODULE, NAME_TYPES_MODULE} from '../../../lib/converter';
import {
AppiumPluginReflectionKind,
CommandReflection,
ExtensionReflection,
} from '../../../lib/model';
import {initAppForPkgs, NAME_FAKE_DRIVER_MODULE} from '../helpers';
const {expect} = chai;
describe('@appium/typedoc-plugin-appium', function () {
describe('plugin', function () {
/**
* Result of {@linkcode convert}
*/
let resolveBeginCtxPromise: Promise<ConvertResult>;
/**
* Result of {@linkcode postProcess}
*/
let resolveEndCtxPromise: Promise<PostProcessResult>;
/**
* Whatever {@linkcode Context} we're using to test
*/
let ctx: Context;
/**
* Array of {@linkcode ExtensionReflection} instances as in a {@linkcode ConvertResult}
*/
let extensionReflections!: ExtensionReflection[];
/**
* Creates a new TypeDoc application and/or resets it
*/
function reset({
entryPoints = [NAME_TYPES_MODULE, NAME_FAKE_DRIVER_MODULE, NAME_BUILTIN_COMMAND_MODULE],
...opts
}: Partial<TypeDocOptions> = {}): Application {
const app = initAppForPkgs({entryPoints, ...opts});
setup(app);
return app;
}
describe('convert()', function () {
describe('when "theme" is not "markdown" or "appium"', function () {
it('should do nothing', async function () {
const app = reset({theme: 'foo'});
resolveBeginCtxPromise = convert(app);
app.convert();
await expect(resolveBeginCtxPromise).to.eventually.not.have.all.keys(
'projectCommands',
'extensionReflections'
);
});
});
describe('when commands are found in the project', function () {
before(async function () {
const app = reset();
resolveBeginCtxPromise = convert(app);
app.convert();
const result = await resolveBeginCtxPromise;
extensionReflections = result.extensionReflections!;
});
it('should sort commands in ascending order by route', function () {
for (const cmdsRefl of extensionReflections) {
let lastRoute = '';
for (const cmdRefl of cmdsRefl.getChildrenByKind(
AppiumPluginReflectionKind.Command as any
) as CommandReflection[]) {
if (lastRoute) {
expect(cmdRefl.route.localeCompare(lastRoute)).to.greaterThanOrEqual(0);
}
lastRoute = cmdRefl.route;
}
}
});
it('should sort exec methods in ascending order by script', function () {
for (const cmdsRefl of extensionReflections) {
let lastScript: string | undefined = undefined;
for (const cmdRefl of cmdsRefl.getChildrenByKind(
AppiumPluginReflectionKind.ExecuteMethod as any
) as CommandReflection[]) {
if (lastScript) {
expect(cmdRefl.script!.localeCompare(lastScript)).to.greaterThanOrEqual(0);
}
lastScript = cmdRefl.script!;
}
}
});
});
describe('when no commands found in the project', function () {
it('should return an object without projectCommands and extensionReflections', async function () {
const app = reset({entryPoints: [NAME_TYPES_MODULE]});
resolveBeginCtxPromise = convert(app);
app.convert();
await expect(resolveBeginCtxPromise).to.eventually.not.have.all.keys(
'projectCommands',
'extensionReflections'
);
});
});
});
describe('postProcess()', function () {
let project: ProjectReflection;
let removed: Set<DeclarationReflection> | undefined;
describe('when the `outputModules` option is false', function () {
before(async function () {
const app = reset();
app.options.setValue('outputModules', false);
resolveBeginCtxPromise = convert(app);
resolveEndCtxPromise = postProcess(app);
app.convert();
[, {ctx, removed}] = await Promise.all([resolveBeginCtxPromise, resolveEndCtxPromise]);
({project} = ctx);
});
it('should mutate the project', function () {
const childRefls = project.getChildrenByKind(AppiumPluginReflectionKind.Extension as any);
expect(childRefls).to.have.lengthOf(project.children!.length).and.to.not.be.empty;
expect(project.getChildrenByKind(ReflectionKind.Module)).to.be.empty;
});
it('should remove DeclarationReflections', function () {
expect(removed).not.to.be.empty;
});
});
describe('when the `outputModules` option is true', function () {
before(async function () {
const app = reset();
app.options.setValue('outputModules', true);
resolveBeginCtxPromise = convert(app);
resolveEndCtxPromise = postProcess(app);
app.convert();
[, {ctx, removed}] = await Promise.all([resolveBeginCtxPromise, resolveEndCtxPromise]);
({project} = ctx);
});
it('should not remove anything from the project', function () {
const defaultRefls = project.getChildrenByKind(
~(AppiumPluginReflectionKind.Extension as any)
);
expect(defaultRefls).to.not.be.empty;
const pluginRefls = project.getChildrenByKind(
AppiumPluginReflectionKind.Extension as any
);
expect(pluginRefls).to.not.be.empty;
});
it('should not remove DeclarationReflections', function () {
expect(removed).to.be.undefined;
});
});
});
});
});
+25
View File
@@ -3,6 +3,31 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [0.9.0](https://github.com/appium/appium/compare/@appium/types@0.8.3...@appium/types@0.9.0) (2023-01-23)
### Bug Fixes
* **types:** update dependency type-fest to v3.5.2 ([64fd8ce](https://github.com/appium/appium/commit/64fd8ce94018b0bb7ccb2baade8d525703f41c45))
* **types:** update dependency type-fest to v3.5.3 ([6c4ba8c](https://github.com/appium/appium/commit/6c4ba8caa508840640f05eea1ab41ecb290312aa))
### Features
* **base-plugin:** add ability for plugins to implement execute methods ([84abed9](https://github.com/appium/appium/commit/84abed920a1dc796ff09013ce86079de5a25fe50))
## [0.8.3](https://github.com/appium/appium/compare/@appium/types@0.8.2...@appium/types@0.8.3) (2023-01-13)
**Note:** Version bump only for package @appium/types
## [0.8.2](https://github.com/appium/appium/compare/@appium/types@0.8.1...@appium/types@0.8.2) (2023-01-13)
**Note:** Version bump only for package @appium/types
+1 -1
View File
@@ -1,4 +1,4 @@
/* tslint:disable */
/* eslint-disable */
/**
* This file was automatically generated by json-schema-to-typescript.
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
+3 -12
View File
@@ -1,8 +1,9 @@
import type {Capabilities as WdioCaps} from '@wdio/types';
import {StandardCapabilities} from './standard-caps';
import {StringRecord, Constraint, Constraints} from '.';
import {BaseDriverCapConstraints} from './constraints';
export type StandardCapabilities = WdioCaps.Capabilities;
export {StandardCapabilities};
export type W3C_APPIUM_PREFIX = 'appium';
/**
@@ -15,16 +16,6 @@ export type BaseCapabilities = ConstraintsToCaps<BaseDriverCapConstraints>;
*/
export type BaseNSCapabilities = CapsToNSCaps<ConstraintsToCaps<BaseDriverCapConstraints>>;
/**
* These may (or should) be reused by drivers.
*/
export type AppiumAndroidCapabilities = WdioCaps.AppiumAndroidCapabilities;
export type AppiumIOSCapabilities = WdioCaps.AppiumIOSCapabilities;
export type AppiumXCUICommandTimeouts = WdioCaps.AppiumXCUICommandTimeouts;
export type AppiumXCUIProcessArguments = WdioCaps.AppiumXCUIProcessArguments;
export type AppiumXCUISafariGlobalPreferences = WdioCaps.AppiumXCUISafariGlobalPreferences;
export type AppiumXCUITestCapabilities = WdioCaps.AppiumXCUITestCapabilities;
/**
* Given a {@linkcode Constraint} `C` and a type `T`, see if `inclusion`/`inclusionCaseInsensitive` is present, and create a union of its allowed literals; otherwise just use `T`.
*/
+1 -8
View File
@@ -12,6 +12,7 @@ import {
BaseDriverCapConstraints,
W3CCapabilities,
Capabilities,
ExecuteMethodMap,
} from '.';
import {ServerArgs} from './config';
import {AsyncReturnType, ConditionalPick} from 'type-fest';
@@ -185,14 +186,6 @@ export interface IExecuteCommands {
executeMethod(script: string, args: [StringRecord] | []): Promise<any>;
}
export interface ExecuteMethodDef<D> {
command: keyof ConditionalPick<Required<D>, DriverCommand>;
params?: {
required?: ReadonlyArray<string>;
optional?: ReadonlyArray<string>;
};
}
export type ExecuteMethodMap<D> = Readonly<Record<string, Readonly<ExecuteMethodDef<D>>>>;
export interface MultiSessionData<
C extends Constraints = BaseDriverCapConstraints,
Extra extends StringRecord | void = void
+22 -3
View File
@@ -5,6 +5,8 @@ import type {Logger} from 'npmlog';
import type {Class as _Class, ConditionalPick, MultidimensionalReadonlyArray} from 'type-fest';
import type {Server as WSServer} from 'ws';
import {ServerArgs} from './config';
import {Driver} from './driver';
import {Plugin, PluginCommand} from './plugin';
export * from './action';
export * from './appium-config';
@@ -82,11 +84,14 @@ export interface AppiumServerSocket extends Socket {
* The definition of an extension method, which will be provided via Appium's API.
*
*/
export interface MethodDef<Ext> {
export interface MethodDef<Ext extends Plugin | Driver> {
/**
* Name of the command.
*/
readonly command?: keyof ConditionalPick<Required<Ext>, DriverCommand>;
readonly command?: keyof ConditionalPick<
Required<Ext>,
Ext extends Plugin ? PluginCommand : Ext extends Driver ? DriverCommand : never
>;
/**
* If true, this `Method` will never proxy.
*/
@@ -97,6 +102,20 @@ export interface MethodDef<Ext> {
readonly payloadParams?: PayloadParams;
}
export interface ExecuteMethodDef<Ext extends Driver | Plugin> {
command: keyof ConditionalPick<
Required<Ext>,
Ext extends Plugin ? PluginCommand : Ext extends Driver ? DriverCommand : never
>;
params?: {
required?: ReadonlyArray<string>;
optional?: ReadonlyArray<string>;
};
}
export type ExecuteMethodMap<Ext extends Driver | Plugin> = Readonly<
Record<string, Readonly<ExecuteMethodDef<Ext>>>
>;
/**
* An instance method of a driver class, whose name may be referenced by {@linkcode MethodDef.command}, and serves as an Appium command.
*
@@ -118,7 +137,7 @@ export interface PayloadParams {
/**
* A mapping of URL paths to HTTP methods to {@linkcode MethodDef}s.
*/
export type MethodMap<Ext = any> = Readonly<
export type MethodMap<Ext extends Plugin | Driver> = Readonly<
Record<
string,
{
+5 -9
View File
@@ -1,5 +1,5 @@
import {MethodMap, UpdateServerCallback, Class, AppiumLogger} from '.';
import {Driver, ExternalDriver} from './driver';
import {AppiumLogger, Class, ExecuteMethodMap, MethodMap, UpdateServerCallback} from '.';
import {ExternalDriver} from './driver';
/**
* The interface describing the constructor and static properties of a Plugin.
@@ -21,6 +21,7 @@ export interface PluginStatic<P extends Plugin> {
* }
*/
newMethodMap?: MethodMap<P>;
executeMethodMap?: ExecuteMethodMap<P>;
}
/**
@@ -44,17 +45,12 @@ export interface Plugin {
/**
* Listener for unexpected server shutdown, which allows a plugin to do cleanup or take custom actions.
*/
onUnexpectedShutdown?: (driver: Driver, cause: Error | string) => Promise<void>;
onUnexpectedShutdown?: (driver: ExternalDriver, cause: Error | string) => Promise<void>;
/**
* Handle an Appium command, optionally running and using or throwing away the value of the
* original Appium behavior (or the behavior of the next plugin in a plugin chain).
*/
handle?: (
next: NextPluginCallback,
driver: Driver,
cmdName: string,
...args: any[]
) => Promise<void>;
handle?: PluginCommand<ExternalDriver, [cmdName: string, ...args: any[]], void>;
}
/**
+65
View File
@@ -0,0 +1,65 @@
export type PageLoadingStrategy = 'none' | 'eager' | 'normal';
export type ProxyTypes = 'pac' | 'noproxy' | 'autodetect' | 'system' | 'manual';
export interface ProxyObject {
proxyType?: ProxyTypes;
proxyAutoconfigUrl?: string;
ftpProxy?: string;
ftpProxyPort?: number;
httpProxy?: string;
httpProxyPort?: number;
sslProxy?: string;
sslProxyPort?: number;
socksProxy?: string;
socksProxyPort?: number;
socksVersion?: string;
socksUsername?: string;
socksPassword?: string;
}
export type Timeouts = Record<'script' | 'pageLoad' | 'implicit', number>;
export interface StandardCapabilities {
/**
* Identifies the user agent.
*/
browserName?: string;
/**
* Identifies the version of the user agent.
*/
browserVersion?: string;
/**
* Identifies the operating system of the endpoint node.
*/
platformName?: string;
/**
* Indicates whether untrusted and self-signed TLS certificates are implicitly trusted on navigation for the duration of the session.
*/
acceptInsecureCerts?: boolean;
/**
* Defines the current session’s page load strategy.
*/
pageLoadStrategy?: PageLoadingStrategy;
/**
* Defines the current session’s proxy configuration.
*/
proxy?: ProxyObject;
/**
* Indicates whether the remote end supports all of the resizing and repositioning commands.
*/
setWindowRect?: boolean;
/**
* Describes the timeouts imposed on certain session operations.
*/
timeouts?: Timeouts;
/**
* Defines the current session’s strict file interactability.
*/
strictFileInteractability?: boolean;
/**
* Describes the current session’s user prompt handler. Defaults to the dismiss and notify state.
*/
unhandledPromptBehavior?: string;
/**
* WebDriver clients opt in to a bidirectional connection by requesting a capability with the name "webSocketUrl" and value true.
*/
webSocketUrl?: boolean;
}
+5 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/types",
"version": "0.8.2",
"version": "0.9.0",
"description": "Various type declarations used across Appium",
"keywords": [
"automation",
@@ -36,13 +36,12 @@
"test:smoke": "node ./index.js"
},
"dependencies": {
"@appium/schema": "^0.2.2",
"@appium/tsconfig": "^0.2.2",
"@appium/schema": "^0.2.3",
"@appium/tsconfig": "^0.2.3",
"@types/express": "4.17.15",
"@types/npmlog": "4.1.4",
"@types/ws": "8.5.4",
"@wdio/types": "7.26.0",
"type-fest": "3.5.1"
"type-fest": "3.5.3"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
@@ -51,7 +50,7 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd",
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72",
"typedoc": {
"entryPoint": "./lib/index.ts"
}
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.0.4](https://github.com/appium/appium-plugins/compare/@appium/universal-xml-plugin@1.0.3...@appium/universal-xml-plugin@1.0.4) (2023-01-13)
**Note:** Version bump only for package @appium/universal-xml-plugin
## [1.0.3](https://github.com/appium/appium-plugins/compare/@appium/universal-xml-plugin@1.0.2...@appium/universal-xml-plugin@1.0.3) (2023-01-13)
**Note:** Version bump only for package @appium/universal-xml-plugin
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@appium/universal-xml-plugin",
"version": "1.0.3",
"version": "1.0.4",
"description": "Appium plugin for making XML source and XPath queries the same across iOS and Android",
"keywords": [
"automation",
@@ -56,7 +56,7 @@
"publishConfig": {
"access": "public"
},
"gitHead": "35f4e2b7e4a82073389d6869cbfce8039b1b4ddd",
"gitHead": "84b211330dc84849af9cc1f3a5c5ad32e15b2e72",
"typedoc": {
"entryPoint": "./lib/index.js"
}