appium
Version:
Automation for Apps.
190 lines (175 loc) • 6.73 kB
text/typescript
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,
};
}