Skip to content

Commit

Permalink
Improve types
Browse files Browse the repository at this point in the history
  • Loading branch information
mykola-mokhnach committed Oct 13, 2023
1 parent 1c8a251 commit 893af96
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 7 deletions.
10 changes: 9 additions & 1 deletion lib/css-converter.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const ALL_ATTRS = [
...STR_ATTRS,
];

/** @type {[string, string[]][]} */
const ATTRIBUTE_ALIASES = [
[RESOURCE_ID, ['id']],
['description', [
Expand Down Expand Up @@ -78,10 +79,12 @@ function toSnakeCase (str) {
* @returns {string} Either 'true' or 'false'. If value is empty, return 'true'
*/
function requireBoolean (css) {
// @ts-ignore Attributes should exist
const val = _.toLower((css.value ?? css.argument)?.value) || 'true'; // an omitted boolean attribute means 'true' (e.g.: input[checked] means checked is true)
if (['true', 'false'].includes(val)) {
return val;
}
// @ts-ignore The attribute should exist
throw new Error(`'${css.name}' must be true, false or empty. Found '${css.value}'`);
}

Expand Down Expand Up @@ -149,6 +152,7 @@ class CssConverter {
* @returns {string} CSS attribute parsed as UiSelector
*/
parseAttr (cssAttr) {
// @ts-ignore Value should be present
const attrValue = cssAttr.value?.value;
if (!_.isString(attrValue) && !_.isEmpty(attrValue)) {
throw new Error(`'${cssAttr.name}=${attrValue}' is an invalid attribute. ` +
Expand Down Expand Up @@ -205,9 +209,10 @@ class CssConverter {
* Convert a CSS pseudo class to a UiSelector
*
* @param {import('css-selector-parser').AstPseudoClass} cssPseudo CSS Pseudo class
* @returns {string?} Pseudo selector parsed as UiSelector
* @returns {string|null|undefined} Pseudo selector parsed as UiSelector
*/
parsePseudo (cssPseudo) {
// @ts-ignore The attribute should exist
const argValue = cssPseudo.argument?.value;
if (!_.isString(argValue) && !_.isEmpty(argValue)) {
throw new Error(`'${cssPseudo.name}=${argValue}'. ` +
Expand Down Expand Up @@ -236,6 +241,7 @@ class CssConverter {
}

let uiAutomatorSelector = 'new UiSelector()';
// @ts-ignore the attribute should exist
const tagName = cssRule.tag?.name;
if (tagName && tagName !== '*') {
let androidClass = [tagName];
Expand All @@ -248,9 +254,11 @@ class CssConverter {
uiAutomatorSelector += `.classNameMatches("${tagName}")`;
}
} else if (!_.isEmpty(cssRule.classNames)) {
// @ts-ignore the attribute should exist
uiAutomatorSelector += `.classNameMatches("${cssRule.classNames.join('\\.')}")`;
}
if (!_.isEmpty(cssRule.ids)) {
// @ts-ignore The attribute should exist
uiAutomatorSelector += `.resourceId("${this.formatIdLocator(cssRule.ids[0])}")`;
}
if (cssRule.attributes) {
Expand Down
23 changes: 21 additions & 2 deletions lib/uiautomator2.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ const INSTRUMENTATION_TARGET = `${SERVER_TEST_PACKAGE_ID}/androidx.test.runner.A
const instrumentationLogger = logger.getLogger('Instrumentation');

class UIA2Proxy extends JWProxy {
/** @type {boolean} */
didInstrumentationExit;

async proxyCommand (url, method, body = null) {
if (this.didInstrumentationExit) {
throw new errors.InvalidContextError(
Expand All @@ -36,6 +39,21 @@ class UIA2Proxy extends JWProxy {
}

class UiAutomator2Server {
/** @type {string} */
host;

/** @type {number} */
systemPort;

/** @type {import('appium-adb').ADB} */
adb;

/** @type {boolean} */
disableWindowAnimation;

/** @type {boolean|undefined} */
disableSuppressAccessibilityService;

constructor (log, opts = {}) {
for (let req of REQD_PARAMS) {
if (!opts || !util.hasValue(opts[req])) {
Expand Down Expand Up @@ -192,6 +210,7 @@ class UiAutomator2Server {
intervalMs: 1000,
});
} catch (err) {
// @ts-ignore It is ok if the attribute does not exist
this.log.error(`Unable to find instrumentation target '${INSTRUMENTATION_TARGET}': ${(pmError || {}).message}`);
if (pmOutput) {
this.log.debug('Available targets:');
Expand Down Expand Up @@ -271,10 +290,10 @@ class UiAutomator2Server {
cmd.push('--no-window-animation');
}
if (_.isBoolean(this.disableSuppressAccessibilityService)) {
cmd.push('-e', 'DISABLE_SUPPRESS_ACCESSIBILITY_SERVICES', this.disableSuppressAccessibilityService);
cmd.push('-e', 'DISABLE_SUPPRESS_ACCESSIBILITY_SERVICES', `${this.disableSuppressAccessibilityService}`);
}
// Disable Google analytics to prevent possible fatal exception
cmd.push('-e', 'disableAnalytics', true);
cmd.push('-e', 'disableAnalytics', 'true');
cmd.push(INSTRUMENTATION_TARGET);
const instrumentationProcess = this.adb.createSubProcess(['shell', ...cmd]);
instrumentationProcess.on('output', (stdout, stderr) => {
Expand Down
4 changes: 2 additions & 2 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { errors } from 'appium/driver';
/**
* Assert the presence of particular keys in the given object
*
* @template {Object} T
* @template {Record<string, any>} T
* @param {string|string[]} argNames one or more key names
* @param {T} opts the object to check
* @returns {T} the same given object
*/
export function requireArgs (argNames, opts = {}) {
export function requireArgs (argNames, opts) {
for (const argName of (_.isArray(argNames) ? argNames : [argNames])) {
if (!_.has(opts, argName)) {
throw new errors.InvalidArgumentError(`'${argName}' argument must be provided`);
Expand Down
5 changes: 3 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
"extends": "@appium/tsconfig/tsconfig.json",
"compilerOptions": {
"outDir": "build",
"strict": true,
"strict": false,
"checkJs": true,
"types": ["node", "mocha", "sinon-chai", "chai-as-promised"]
},
"include": ["lib", "test", "index.js"]
"include": ["lib", "index.js"]
}

0 comments on commit 893af96

Please sign in to comment.