UNPKG

appium-xcuitest-driver

Version:

Appium driver for iOS using XCUITest for backend

96 lines 3.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ClassChainEmitter = void 0; const driver_1 = require("appium/driver"); const utils_1 = require("../utils"); const BOOLEAN_ATTRS = new Set(['visible', 'accessible', 'accessibility-container', 'enabled']); const STRING_ATTRS = new Set(['label', 'name', 'value', 'type']); /** Converts parsed CSS selectors into class chain strings. */ class ClassChainEmitter { strategy; constructor(strategy) { this.strategy = strategy; } emit(parsed) { return this.emitRule(parsed.rule); } emitRule(rule) { if (rule.classes.length) { throw new driver_1.errors.InvalidSelectorError(`'${rule.classes.join('.')}' is not a valid class. Must be a single string ` + `(e.g.: XCUIElementTypeWindow) without dots separating them`); } let tagName = rule.tag ?? ''; if (tagName && tagName !== '*' && !tagName.toLowerCase().startsWith('xcuielementtype')) { const capitalizedTagName = tagName.charAt(0).toUpperCase() + tagName.slice(1); tagName = `XCUIElementType${capitalizedTagName}`; } let classChainSelector = tagName || '*'; const attrs = []; if (rule.id) { attrs.push(`name == "${rule.id}"`); } for (const attr of rule.attributes) { attrs.push(this.formatEntity(attr)); } for (const pseudo of rule.pseudos) { attrs.push(this.formatEntity(pseudo)); } const nonIndexAttrs = attrs.filter((attr) => typeof attr === 'string'); if (!(0, utils_1.isEmpty)(nonIndexAttrs)) { classChainSelector += `[\`${nonIndexAttrs.join(' AND ')}\`]`; } const indexAttr = attrs.find((attr) => typeof attr === 'object' && attr !== null && attr.index !== undefined); if (indexAttr) { classChainSelector += `[${indexAttr.index}]`; } if (rule.nested) { classChainSelector += `/${this.emitRule(rule.nested)}`; } return rule.combinator === 'child' ? classChainSelector : `**/${classChainSelector}`; } formatEntity(attr) { if (attr.name === 'index') { return this.formatIndex(attr.value); } if (BOOLEAN_ATTRS.has(attr.name)) { return this.formatBooleanAttr(attr.name, attr.value); } if (STRING_ATTRS.has(attr.name)) { return this.formatStringAttr(attr); } } formatIndex(value) { return { index: value ?? '' }; } formatBooleanAttr(name, value) { return `${this.toCamelCase(name)} == ${value ?? '1'}`; } formatStringAttr(attr) { const attrName = this.toCamelCase(attr.name); const value = attr.value ?? ''; if (value === '') { return `[${attrName} LIKE ${value}]`; } switch (attr.operator) { case '=': return `${attrName} == "${value}"`; case '*=': return `${attrName} MATCHES "${(0, utils_1.escapeRegExp)(value)}"`; case '^=': return `${attrName} BEGINSWITH "${value}"`; case '$=': return `${attrName} ENDSWITH "${value}"`; case '~=': return `${attrName} CONTAINS "${value}"`; default: return `${attrName} == "${value}"`; } } toCamelCase(str) { const tokens = str.split('-').map((token) => token.charAt(0).toUpperCase() + token.slice(1).toLowerCase()); const out = tokens.join(''); return out.charAt(0).toLowerCase() + out.slice(1); } } exports.ClassChainEmitter = ClassChainEmitter; //# sourceMappingURL=class-chain-emitter.js.map