UNPKG

@appium/base-driver

Version:

Base driver class for Appium drivers

84 lines (71 loc) 2.7 kB
import type {Constraints, W3CCapabilities, Capabilities, AppiumLogger} from '@appium/types'; import _ from 'lodash'; /** * Determine whether the given argument is valid * W3C capabilities instance. */ export function isW3cCaps(caps: unknown): caps is W3CCapabilities<Constraints> { if (!_.isPlainObject(caps)) { return false; } const c = caps as Record<string, unknown>; const isFirstMatchValid = () => _.isArray(c.firstMatch) && !_.isEmpty(c.firstMatch) && _.every(c.firstMatch, _.isPlainObject); const isAlwaysMatchValid = () => _.isPlainObject(c.alwaysMatch); if (_.has(c, 'firstMatch') && _.has(c, 'alwaysMatch')) { return isFirstMatchValid() && isAlwaysMatchValid(); } if (_.has(c, 'firstMatch')) { return isFirstMatchValid(); } if (_.has(c, 'alwaysMatch')) { return isAlwaysMatchValid(); } return false; } /** * Normalize capability values according to constraints (e.g. string 'true' → boolean). */ export function fixCaps<C extends Constraints>( oldCaps: Record<string, unknown>, desiredCapConstraints: C, log: AppiumLogger ): Capabilities<C> { const caps = _.clone(oldCaps) as Record<string, unknown>; const logCastWarning = (prefix: string) => log.warn(`${prefix}. This may cause unexpected behavior`); // boolean capabilities can be passed in as strings 'false' and 'true' // which we want to translate into boolean values const booleanCaps = _.keys(_.pickBy(desiredCapConstraints, (k) => k.isBoolean === true)); for (const cap of booleanCaps) { const value = oldCaps[cap]; if (!_.isString(value)) { continue; } if (!['true', 'false'].includes(value.toLowerCase())) { logCastWarning(`String capability '${cap}' ('${value}') cannot be converted to a boolean`); continue; } logCastWarning(`Capability '${cap}' changed from string '${value}' to boolean`); caps[cap] = value.toLowerCase() === 'true'; } // int capabilities are often sent in as strings by frameworks const intCaps = _.keys(_.pickBy(desiredCapConstraints, (k) => k.isNumber === true)); for (const cap of intCaps) { const value = oldCaps[cap]; if (!_.isString(value)) { continue; } const intValue = parseInt(value as string, 10); const floatValue = parseFloat(value as string); const newValue = floatValue !== intValue ? floatValue : intValue; if (Number.isNaN(newValue)) { logCastWarning(`String capability '${cap}' ('${value}') cannot be converted to a number`); continue; } logCastWarning(`Capability '${cap}' changed from string '${value}' to number ${newValue}`); caps[cap] = newValue; } return caps as Capabilities<C>; }