mirror of
https://github.com/appium/appium.git
synced 2026-05-08 11:59:29 -05:00
feat: Add /appium/extensions API to list available extensions (#20931)
This commit is contained in:
@@ -9,11 +9,10 @@ import {
|
||||
DELETE_SESSION_COMMAND,
|
||||
GET_STATUS_COMMAND,
|
||||
LIST_DRIVER_COMMANDS_COMMAND,
|
||||
LIST_DRIVER_EXTENSIONS_COMMAND,
|
||||
promoteAppiumOptions,
|
||||
promoteAppiumOptionsForObject,
|
||||
generateDriverLogPrefix,
|
||||
METHOD_MAP as BASE_METHOD_MAP,
|
||||
BIDI_COMMANDS as BASE_BIDI_COMMANDS,
|
||||
} from '@appium/base-driver';
|
||||
import AsyncLock from 'async-lock';
|
||||
import {
|
||||
@@ -21,13 +20,12 @@ import {
|
||||
pullSettings,
|
||||
makeNonW3cCapsError,
|
||||
validateFeatures,
|
||||
toRestCommandsMap,
|
||||
toBiDiCommandsMap,
|
||||
} from './utils';
|
||||
import {util} from '@appium/support';
|
||||
import {getDefaultsForExtension} from './schema';
|
||||
import {DRIVER_TYPE, BIDI_BASE_PATH} from './constants';
|
||||
import * as bidiHelpers from './bidi';
|
||||
import * as inspectorCommands from './inspector-commands';
|
||||
|
||||
const desiredCapabilityConstraints = /** @type {const} */ ({
|
||||
automationName: {
|
||||
@@ -570,36 +568,6 @@ class AppiumDriver extends DriverCore {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} sessionId
|
||||
* @returns {import('@appium/types').ListCommandsResponse}
|
||||
*/
|
||||
listCommands(sessionId) {
|
||||
/** @type {import('@appium/types').MethodMap<any>} */
|
||||
let driverRestMethodMap = {};
|
||||
/** @type {import('@appium/types').BidiModuleMap} */
|
||||
let driverBiDiCommands = {};
|
||||
/** @type {Record<string, import('@appium/types').MethodMap<any>>} */
|
||||
let pluginRestMethodMaps = {};
|
||||
/** @type {Record<string, import('@appium/types').BidiModuleMap>} */
|
||||
let pluginBiDiCommands = {};
|
||||
if (sessionId) {
|
||||
const driverClass = /** @type {import('@appium/types').DriverClass | undefined} */ (
|
||||
this.driverForSession(sessionId)?.constructor
|
||||
);
|
||||
driverRestMethodMap = driverClass?.newMethodMap ?? {};
|
||||
driverBiDiCommands = driverClass?.newBidiCommands ?? {};
|
||||
const pluginClasses = this.pluginsForSession(sessionId)
|
||||
.map((p) => /** @type {import('@appium/types').PluginClass} */ (p.constructor));
|
||||
pluginRestMethodMaps = _.fromPairs(pluginClasses.map((c) => [c.name, c.newMethodMap ?? {}]));
|
||||
pluginBiDiCommands = _.fromPairs(pluginClasses.map((c) => [c.name, c.newBidiCommands ?? {}]));
|
||||
}
|
||||
return {
|
||||
rest: toRestCommandsMap(BASE_METHOD_MAP, driverRestMethodMap, pluginRestMethodMaps),
|
||||
bidi: toBiDiCommandsMap(BASE_BIDI_COMMANDS, driverBiDiCommands, pluginBiDiCommands),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} sessionId
|
||||
*/
|
||||
@@ -973,6 +941,8 @@ class AppiumDriver extends DriverCore {
|
||||
onBidiConnection = bidiHelpers.onBidiConnection;
|
||||
onBidiMessage = bidiHelpers.onBidiMessage;
|
||||
onBidiServerError = bidiHelpers.onBidiServerError;
|
||||
listCommands = inspectorCommands.listCommands;
|
||||
listExtensions = inspectorCommands.listExtensions;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -983,7 +953,11 @@ class AppiumDriver extends DriverCore {
|
||||
*/
|
||||
function isAppiumDriverCommand(cmd) {
|
||||
return !isSessionCommand(cmd)
|
||||
|| _.includes([DELETE_SESSION_COMMAND, LIST_DRIVER_COMMANDS_COMMAND], cmd);
|
||||
|| _.includes([
|
||||
DELETE_SESSION_COMMAND,
|
||||
LIST_DRIVER_COMMANDS_COMMAND,
|
||||
LIST_DRIVER_EXTENSIONS_COMMAND,
|
||||
], cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
METHOD_MAP as BASE_METHOD_MAP,
|
||||
BIDI_COMMANDS as BASE_BIDI_COMMANDS,
|
||||
} from '@appium/base-driver';
|
||||
import type {
|
||||
ListCommandsResponse,
|
||||
MethodMap,
|
||||
BidiModuleMap,
|
||||
DriverClass,
|
||||
PluginClass,
|
||||
ListExtensionsResponse,
|
||||
PayloadParams,
|
||||
RestCommandItemParam,
|
||||
RestMethodsToCommandsMap,
|
||||
BiDiCommandsMap,
|
||||
BidiMethodParams,
|
||||
BiDiCommandItemParam,
|
||||
BiDiCommandNamesToInfosMap,
|
||||
ExecuteMethodMap,
|
||||
} from '@appium/types';
|
||||
import type { AppiumDriver } from './appium';
|
||||
|
||||
|
||||
export async function listCommands(this: AppiumDriver, sessionId?: string): Promise<ListCommandsResponse> {
|
||||
let driverRestMethodMap: MethodMap<any> = {};
|
||||
let driverBiDiCommands: BidiModuleMap = {};
|
||||
let pluginRestMethodMaps: Record<string, MethodMap<any>> = {};
|
||||
let pluginBiDiCommands: Record<string, BidiModuleMap> = {};
|
||||
if (sessionId) {
|
||||
const driverClass = this.driverForSession(sessionId)?.constructor as (DriverClass | undefined);
|
||||
driverRestMethodMap = driverClass?.newMethodMap ?? {};
|
||||
driverBiDiCommands = driverClass?.newBidiCommands ?? {};
|
||||
const pluginClasses = this.pluginsForSession(sessionId)
|
||||
.map((p) => p.constructor as PluginClass);
|
||||
pluginRestMethodMaps = _.fromPairs(pluginClasses.map((c) => [c.name, c.newMethodMap ?? {}]));
|
||||
pluginBiDiCommands = _.fromPairs(pluginClasses.map((c) => [c.name, c.newBidiCommands ?? {}]));
|
||||
}
|
||||
return {
|
||||
rest: {
|
||||
base: methodMapToRestCommandsInfo(BASE_METHOD_MAP),
|
||||
driver: methodMapToRestCommandsInfo(driverRestMethodMap),
|
||||
plugins: pluginRestMethodMaps ? _.mapValues(pluginRestMethodMaps, methodMapToRestCommandsInfo) : undefined,
|
||||
},
|
||||
bidi: toBiDiCommandsMap(BASE_BIDI_COMMANDS, driverBiDiCommands, pluginBiDiCommands),
|
||||
};
|
||||
}
|
||||
|
||||
export async function listExtensions(this: AppiumDriver, sessionId?: string): Promise<ListExtensionsResponse> {
|
||||
let driverExecuteMethodMap: ExecuteMethodMap<any> = {};
|
||||
let pluginExecuteMethodMaps: Record<string, ExecuteMethodMap<any>> = {};
|
||||
if (sessionId) {
|
||||
const driverClass = this.driverForSession(sessionId)?.constructor as (DriverClass | undefined);
|
||||
driverExecuteMethodMap = driverClass?.executeMethodMap ?? {};
|
||||
const pluginClasses = this.pluginsForSession(sessionId)
|
||||
.map((p) => p.constructor as PluginClass);
|
||||
pluginExecuteMethodMaps = _.fromPairs(pluginClasses.map((c) => [c.name, c.executeMethodMap ?? {}]));
|
||||
}
|
||||
return {
|
||||
rest: {
|
||||
driver: executeMethodMapToCommandsInfo(driverExecuteMethodMap),
|
||||
plugins: pluginExecuteMethodMaps ? _.mapValues(pluginExecuteMethodMaps, executeMethodMapToCommandsInfo) : undefined,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function toRestCommandParams(params: PayloadParams | undefined): RestCommandItemParam[] | undefined {
|
||||
if (!params) {
|
||||
return;
|
||||
}
|
||||
|
||||
const toRestCommandItemParam = (x: any, isRequired: boolean): RestCommandItemParam | undefined => {
|
||||
const isNameAnArray = _.isArray(x);
|
||||
const name = isNameAnArray ? x[0] : x;
|
||||
if (!_.isString(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If parameter names are arrays then this means
|
||||
// either of them is required.
|
||||
// Not sure we could reflect that in here.
|
||||
const required = isRequired && !isNameAnArray;
|
||||
return {
|
||||
name,
|
||||
required,
|
||||
};
|
||||
};
|
||||
|
||||
const requiredParams: RestCommandItemParam[] = (params.required ?? [])
|
||||
.map((name: any) => toRestCommandItemParam(name, true))
|
||||
.filter((x) => !_.isUndefined(x));
|
||||
const optionalParams: RestCommandItemParam[] = (params.optional ?? [])
|
||||
.map((name: any) => toRestCommandItemParam(name, false))
|
||||
.filter((x) => !_.isUndefined(x));
|
||||
return requiredParams.length || optionalParams.length
|
||||
? [...requiredParams, ...optionalParams]
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function methodMapToRestCommandsInfo (mm: MethodMap<any>): Record<string, RestMethodsToCommandsMap> {
|
||||
const res: Record<string, RestMethodsToCommandsMap> = {};
|
||||
for (const [uriPath, methods] of _.toPairs(mm)) {
|
||||
const methodsMap = {};
|
||||
for (const [method, spec] of _.toPairs(methods)) {
|
||||
methodsMap[method] = {
|
||||
command: spec.command,
|
||||
deprecated: spec.deprecated,
|
||||
info: spec.info,
|
||||
params: toRestCommandParams(spec.payloadParams),
|
||||
};
|
||||
}
|
||||
res[uriPath] = methodsMap;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function executeMethodMapToCommandsInfo(emm: ExecuteMethodMap<any>): RestMethodsToCommandsMap {
|
||||
const result: RestMethodsToCommandsMap = {};
|
||||
for (const [name, info] of _.toPairs(emm)) {
|
||||
result[name] = {
|
||||
command: info.command,
|
||||
deprecated: info.deprecated,
|
||||
info: info.info,
|
||||
params: toRestCommandParams(info.params),
|
||||
};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function toBiDiCommandsMap(
|
||||
baseModuleMap: BidiModuleMap,
|
||||
driverModuleMap: BidiModuleMap,
|
||||
pluginModuleMaps: Record<string, BidiModuleMap>
|
||||
): BiDiCommandsMap {
|
||||
const toBiDiCommandParams = (params: BidiMethodParams | undefined): BiDiCommandItemParam[] | undefined => {
|
||||
if (!params) {
|
||||
return;
|
||||
}
|
||||
|
||||
const toBiDiCommandItemParam = (x: any, isRequired: boolean): BiDiCommandItemParam | undefined => {
|
||||
const isNameAnArray = _.isArray(x);
|
||||
const name = isNameAnArray ? x[0] : x;
|
||||
if (!_.isString(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If parameter names are arrays then this means
|
||||
// either of them is required.
|
||||
// Not sure we could reflect that in here.
|
||||
const required = isRequired && !isNameAnArray;
|
||||
return {
|
||||
name,
|
||||
required,
|
||||
};
|
||||
};
|
||||
|
||||
const requiredParams: BiDiCommandItemParam[] = (params.required ?? [])
|
||||
.map((name) => toBiDiCommandItemParam(name, true))
|
||||
.filter((x) => !_.isUndefined(x));
|
||||
const optionalParams: BiDiCommandItemParam[] = (params.optional ?? [])
|
||||
.map((name) => toBiDiCommandItemParam(name, false))
|
||||
.filter((x) => !_.isUndefined(x));
|
||||
return requiredParams.length || optionalParams.length
|
||||
? [...requiredParams, ...optionalParams]
|
||||
: undefined;
|
||||
};
|
||||
|
||||
const moduleMapToBiDiCommandsInfo = (mm: BidiModuleMap): Record<string, BiDiCommandNamesToInfosMap> => {
|
||||
const res: Record<string, BiDiCommandNamesToInfosMap> = {};
|
||||
for (const [domain, commands] of _.toPairs(mm)) {
|
||||
const commandsMap = {};
|
||||
for (const [name, spec] of _.toPairs(commands)) {
|
||||
commandsMap[name] = {
|
||||
command: spec.command,
|
||||
deprecated: spec.deprecated,
|
||||
info: spec.info,
|
||||
params: toBiDiCommandParams(spec.params),
|
||||
};
|
||||
}
|
||||
res[domain] = commandsMap;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
return {
|
||||
base: moduleMapToBiDiCommandsInfo(baseModuleMap),
|
||||
driver: moduleMapToBiDiCommandsInfo(driverModuleMap),
|
||||
plugins: pluginModuleMaps ? _.mapValues(pluginModuleMaps, moduleMapToBiDiCommandsInfo) : undefined,
|
||||
};
|
||||
}
|
||||
@@ -494,174 +494,6 @@ export function validateFeatures(features) {
|
||||
return features.map(validator);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import('@appium/types').MethodMap<any>} baseMethodMap
|
||||
* @param {import('@appium/types').MethodMap<any>} driverMethodMap
|
||||
* @param {Record<string, import('@appium/types').MethodMap<any>>} [pluginMethodMaps]
|
||||
* @returns {import('@appium/types').RestCommandsMap}
|
||||
*/
|
||||
export function toRestCommandsMap(baseMethodMap, driverMethodMap, pluginMethodMaps) {
|
||||
/**
|
||||
* @param {import("@appium/types").PayloadParams | undefined} params
|
||||
* @returns {import("@appium/types").RestCommandItemParam[] | undefined}
|
||||
*/
|
||||
const toRestCommandParams = (params) => {
|
||||
if (!params) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {any} x
|
||||
* @param {boolean} isRequired
|
||||
* @returns {import("@appium/types").RestCommandItemParam | undefined}
|
||||
*/
|
||||
const toRestCommandItemParam = (x, isRequired) => {
|
||||
const isNameAnArray = _.isArray(x);
|
||||
const name = isNameAnArray ? x[0] : x;
|
||||
if (!_.isString(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If parameter names are arrays then this means
|
||||
// either of them is required.
|
||||
// Not sure we could reflect that in here.
|
||||
const required = isRequired && !isNameAnArray;
|
||||
return {
|
||||
name,
|
||||
required,
|
||||
};
|
||||
};
|
||||
|
||||
/** @type {import("@appium/types").RestCommandItemParam[]} */
|
||||
const requiredParams = (params.required ?? [])
|
||||
.map((name) => toRestCommandItemParam(name, true))
|
||||
.filter((x) => !_.isUndefined(x));
|
||||
/** @type {import("@appium/types").RestCommandItemParam[]} */
|
||||
const optionalParams = (params.optional ?? [])
|
||||
.map((name) => toRestCommandItemParam(name, false))
|
||||
.filter((x) => !_.isUndefined(x));
|
||||
return requiredParams.length || optionalParams.length
|
||||
? [...requiredParams, ...optionalParams]
|
||||
: undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import('@appium/types').MethodMap<any>} mm
|
||||
* @returns {Record<string, import('@appium/types').RestMethodsToCommandsMap>}
|
||||
*/
|
||||
const methodMapToRestCommandsInfo = (mm) => {
|
||||
/** @type {Record<string, import('@appium/types').RestMethodsToCommandsMap>} */
|
||||
const res = {};
|
||||
for (const [uriPath, methods] of _.toPairs(mm)) {
|
||||
const methodsMap = {};
|
||||
for (const [method, spec] of _.toPairs(methods)) {
|
||||
methodsMap[method] = {
|
||||
command: spec.command,
|
||||
deprecated: spec.deprecated,
|
||||
info: spec.info,
|
||||
params: toRestCommandParams(spec.payloadParams),
|
||||
};
|
||||
}
|
||||
// @ts-ignore this is OK
|
||||
res[uriPath] = methodsMap;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
return {
|
||||
base: methodMapToRestCommandsInfo(baseMethodMap),
|
||||
driver: methodMapToRestCommandsInfo(driverMethodMap),
|
||||
plugins: pluginMethodMaps ? _.mapValues(pluginMethodMaps, methodMapToRestCommandsInfo) : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import('@appium/types').BidiModuleMap} baseModuleMap
|
||||
* @param {import('@appium/types').BidiModuleMap} driverModuleMap
|
||||
* @param {Record<string, import('@appium/types').BidiModuleMap>} [pluginModuleMaps]
|
||||
* @returns {import('@appium/types').BiDiCommandsMap}
|
||||
*/
|
||||
export function toBiDiCommandsMap(baseModuleMap, driverModuleMap, pluginModuleMaps) {
|
||||
/**
|
||||
* @param {import("@appium/types").BidiMethodParams | undefined} params
|
||||
* @returns {import("@appium/types").BiDiCommandItemParam[] | undefined}
|
||||
*/
|
||||
const toBiDiCommandParams = (params) => {
|
||||
if (!params) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {any} x
|
||||
* @param {boolean} isRequired
|
||||
* @returns {import("@appium/types").BiDiCommandItemParam | undefined}
|
||||
*/
|
||||
const toBiDiCommandItemParam = (x, isRequired) => {
|
||||
const isNameAnArray = _.isArray(x);
|
||||
const name = isNameAnArray ? x[0] : x;
|
||||
if (!_.isString(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If parameter names are arrays then this means
|
||||
// either of them is required.
|
||||
// Not sure we could reflect that in here.
|
||||
const required = isRequired && !isNameAnArray;
|
||||
return {
|
||||
name,
|
||||
required,
|
||||
};
|
||||
};
|
||||
|
||||
/** @type {import("@appium/types").BiDiCommandItemParam[]} */
|
||||
const requiredParams = (params.required ?? [])
|
||||
.map((name) => toBiDiCommandItemParam(name, true))
|
||||
.filter((x) => !_.isUndefined(x));
|
||||
/** @type {import("@appium/types").BiDiCommandItemParam[]} */
|
||||
const optionalParams = (params.optional ?? [])
|
||||
.map((name) => toBiDiCommandItemParam(name, false))
|
||||
.filter((x) => !_.isUndefined(x));
|
||||
return requiredParams.length || optionalParams.length
|
||||
? [...requiredParams, ...optionalParams]
|
||||
: undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import('@appium/types').BidiModuleMap} mm
|
||||
* @returns {Record<string, import('@appium/types').BiDiCommandNamesToInfosMap>}
|
||||
*/
|
||||
const moduleMapToBiDiCommandsInfo = (mm) => {
|
||||
/** @type {Record<string, import('@appium/types').BiDiCommandNamesToInfosMap>} */
|
||||
const res = {};
|
||||
for (const [domain, commands] of _.toPairs(mm)) {
|
||||
const commandsMap = {};
|
||||
for (const [name, spec] of _.toPairs(commands)) {
|
||||
commandsMap[name] = {
|
||||
command: spec.command,
|
||||
deprecated: spec.deprecated,
|
||||
info: spec.info,
|
||||
params: toBiDiCommandParams(spec.params),
|
||||
};
|
||||
}
|
||||
// @ts-ignore this is OK
|
||||
res[domain] = commandsMap;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
return {
|
||||
base: moduleMapToBiDiCommandsInfo(baseModuleMap),
|
||||
driver: moduleMapToBiDiCommandsInfo(driverModuleMap),
|
||||
plugins: pluginModuleMaps ? _.mapValues(pluginModuleMaps, moduleMapToBiDiCommandsInfo) : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {import('@appium/types').StringRecord} StringRecord
|
||||
* @typedef {import('@appium/types').BaseDriverCapConstraints} BaseDriverCapConstraints
|
||||
|
||||
@@ -225,7 +225,7 @@ describe('FakeDriver via HTTP', function () {
|
||||
it('should list available driver commands', async function () {
|
||||
driver.addCommand(
|
||||
'listCommands',
|
||||
async () => (await axios.post(
|
||||
async () => (await axios.get(
|
||||
`${testServerBaseSessionUrl}/${driver.sessionId}/appium/commands`
|
||||
)).data.value
|
||||
);
|
||||
@@ -256,6 +256,27 @@ describe('FakeDriver via HTTP', function () {
|
||||
_.size(commands.bidi.base).should.be.greaterThan(1);
|
||||
_.size(commands.bidi.driver).should.be.greaterThan(0);
|
||||
});
|
||||
|
||||
it('should list available driver extensions', async function () {
|
||||
driver.addCommand(
|
||||
'listExtensions',
|
||||
async () => (await axios.get(
|
||||
`${testServerBaseSessionUrl}/${driver.sessionId}/appium/extensions`
|
||||
)).data.value
|
||||
);
|
||||
|
||||
const extensions = await driver.listExtensions();
|
||||
JSON.stringify(extensions.rest.driver['fake: setThing']).should.eql(
|
||||
JSON.stringify({
|
||||
command: 'setFakeThing',
|
||||
params: [{
|
||||
name: 'thing',
|
||||
required: true
|
||||
}]
|
||||
})
|
||||
);
|
||||
_.size(extensions.rest.driver).should.be.greaterThan(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('session handling', function () {
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import type {Constraints, IInspectorCommands, ListCommandsResponse} from '@appium/types';
|
||||
import type {
|
||||
Constraints,
|
||||
IInspectorCommands,
|
||||
ListCommandsResponse,
|
||||
ListExtensionsResponse,
|
||||
} from '@appium/types';
|
||||
import {mixin} from './mixin';
|
||||
|
||||
declare module '../driver' {
|
||||
@@ -15,9 +20,20 @@ const InspectorCommands: IInspectorCommands = {
|
||||
* @returns
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
listCommands(sessionId?: string | null): ListCommandsResponse {
|
||||
async listCommands(sessionId?: string | null): Promise<ListCommandsResponse> {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* This command is supposed to be handled by the umbrella driver.
|
||||
*
|
||||
* @param sessionId
|
||||
* @returns
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async listExtensions(sessionId?: string | null): Promise<ListExtensionsResponse> {
|
||||
return {};
|
||||
},
|
||||
};
|
||||
|
||||
mixin(InspectorCommands);
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
DELETE_SESSION_COMMAND,
|
||||
GET_STATUS_COMMAND,
|
||||
LIST_DRIVER_COMMANDS_COMMAND,
|
||||
LIST_DRIVER_EXTENSIONS_COMMAND,
|
||||
makeArgs,
|
||||
checkParams,
|
||||
validateExecuteMethodParams,
|
||||
@@ -32,4 +33,5 @@ export {
|
||||
DELETE_SESSION_COMMAND,
|
||||
GET_STATUS_COMMAND,
|
||||
LIST_DRIVER_COMMANDS_COMMAND,
|
||||
LIST_DRIVER_EXTENSIONS_COMMAND,
|
||||
};
|
||||
|
||||
@@ -20,6 +20,7 @@ export const CREATE_SESSION_COMMAND = 'createSession';
|
||||
export const DELETE_SESSION_COMMAND = 'deleteSession';
|
||||
export const GET_STATUS_COMMAND = 'getStatus';
|
||||
export const LIST_DRIVER_COMMANDS_COMMAND = 'listCommands';
|
||||
export const LIST_DRIVER_EXTENSIONS_COMMAND = 'listExtensions';
|
||||
|
||||
/** @type {Set<string>} */
|
||||
const deprecatedCommandsLogged = new Set();
|
||||
|
||||
@@ -871,7 +871,10 @@ export const METHOD_MAP = /** @type {const} */ ({
|
||||
// #region Inspector
|
||||
|
||||
'/session/:sessionId/appium/commands': {
|
||||
POST: {command: 'listCommands'},
|
||||
GET: {command: 'listCommands'},
|
||||
},
|
||||
'/session/:sessionId/appium/extensions': {
|
||||
GET: {command: 'listExtensions'},
|
||||
},
|
||||
|
||||
// #endregion
|
||||
|
||||
@@ -41,7 +41,7 @@ describe('Protocol', function () {
|
||||
}
|
||||
let hash = shasum.digest('hex').substring(0, 8);
|
||||
// Modify the hash whenever the protocol has intentionally been modified.
|
||||
hash.should.equal('3590ffcf');
|
||||
hash.should.equal('392df577');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -274,7 +274,7 @@ export interface BiDiCommandItem {
|
||||
}
|
||||
|
||||
export interface BiDiCommandNamesToInfosMap {
|
||||
[name: string]: Record<string, BiDiCommandItem>;
|
||||
[name: string]: BiDiCommandItem;
|
||||
}
|
||||
|
||||
export interface BiDiCommandsMap {
|
||||
@@ -302,3 +302,21 @@ export interface ListCommandsResponse {
|
||||
*/
|
||||
bidi?: BiDiCommandsMap;
|
||||
}
|
||||
|
||||
export interface RestExtensionsMap {
|
||||
/**
|
||||
* Driver execute methods mapping
|
||||
*/
|
||||
driver: RestMethodsToCommandsMap;
|
||||
/**
|
||||
* Plugins execute methods mapping
|
||||
*/
|
||||
plugins?: Record<string, RestMethodsToCommandsMap>;
|
||||
}
|
||||
|
||||
export interface ListExtensionsResponse {
|
||||
/**
|
||||
* Rest extensions mapping
|
||||
*/
|
||||
rest?: RestExtensionsMap;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
ExecuteMethodMap,
|
||||
MethodMap,
|
||||
ListCommandsResponse,
|
||||
ListExtensionsResponse,
|
||||
} from './command';
|
||||
import type {ServerArgs} from './config';
|
||||
import type {HTTPHeaders, HTTPMethod} from './http';
|
||||
@@ -360,7 +361,8 @@ export interface IBidiCommands {
|
||||
}
|
||||
|
||||
export interface IInspectorCommands {
|
||||
listCommands(): ListCommandsResponse;
|
||||
listCommands(): Promise<ListCommandsResponse>;
|
||||
listExtensions(): Promise<ListExtensionsResponse>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user