|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- "use strict";
- var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.findStrategy = void 0;
- const fs_1 = __importDefault(require("fs"));
- const lodash_isplainobject_1 = __importDefault(require("lodash.isplainobject"));
- const constants_1 = require("../constants");
- const DEFAULT_STRATEGY = 'css selector';
- const DIRECT_SELECTOR_REGEXP = /^(id|css selector|xpath|link text|partial link text|name|tag name|class name|-android uiautomator|-android datamatcher|-android viewmatcher|-android viewtag|-ios uiautomation|-ios predicate string|-ios class chain|accessibility id):(.+)/;
- const XPATH_SELECTORS_START = [
- '/', '(', '../', './', '*/'
- ];
- const NAME_MOBILE_SELECTORS_START = [
- 'uia', 'xcuielementtype', 'android.widget', 'cyi'
- ];
- const XPATH_SELECTOR_REGEXP = [
- /^([a-z0-9|-]*)/,
- /(?:(\.|#)(-?[_a-zA-Z]+[_a-zA-Z0-9-]*))?/,
- /(?:\[(-?[_a-zA-Z]+[_a-zA-Z0-9-]*)(?:=(?:"|')([a-zA-z0-9\-_. ]+)(?:"|'))?\])?/,
- /(\*)?=(.+)$/,
- ];
- const IMAGEPATH_MOBILE_SELECTORS_ENDSWITH = [
- '.jpg', '.jpeg', '.gif', '.png', '.bmp', '.svg'
- ];
- const defineStrategy = function (selector) {
- if (lodash_isplainobject_1.default(selector)) {
- if (JSON.stringify(selector).indexOf('test.espresso.matcher.ViewMatchers') < 0)
- return '-android datamatcher';
- return '-android viewmatcher';
- }
- const stringSelector = selector;
- if (stringSelector.match(DIRECT_SELECTOR_REGEXP)) {
- return 'directly';
- }
- if (IMAGEPATH_MOBILE_SELECTORS_ENDSWITH.some(path => stringSelector.toLowerCase().endsWith(path))) {
- return '-image';
- }
- if (XPATH_SELECTORS_START.some(option => stringSelector.startsWith(option))) {
- return 'xpath';
- }
- if (stringSelector.startsWith('=')) {
- return 'link text';
- }
- if (stringSelector.startsWith('*=')) {
- return 'partial link text';
- }
- if (stringSelector.startsWith('id=')) {
- return 'id';
- }
- if (stringSelector.startsWith('android=')) {
- return '-android uiautomator';
- }
- if (stringSelector.startsWith('ios=')) {
- return '-ios uiautomation';
- }
- if (stringSelector.startsWith('~')) {
- return 'accessibility id';
- }
- if (NAME_MOBILE_SELECTORS_START.some(option => stringSelector.toLowerCase().startsWith(option))) {
- return 'class name';
- }
- if (stringSelector.search(/<[0-9a-zA-Z-]+( \/)*>/g) >= 0) {
- return 'tag name';
- }
- if (stringSelector.search(/^\[name=("|')([a-zA-z0-9\-_.@=[\] ']+)("|')]$/) >= 0) {
- return 'name';
- }
- if (selector === '..' || selector === '.') {
- return 'xpath';
- }
- if (stringSelector.match(new RegExp(XPATH_SELECTOR_REGEXP.map(rx => rx.source).join('')))) {
- return 'xpath extended';
- }
- };
- exports.findStrategy = function (selector, isW3C, isMobile) {
- const stringSelector = selector;
- let using = DEFAULT_STRATEGY;
- let value = selector;
- switch (defineStrategy(selector)) {
- case 'directly': {
- const match = stringSelector.match(DIRECT_SELECTOR_REGEXP);
- if (!match || !isMobile && isW3C && !constants_1.W3C_SELECTOR_STRATEGIES.includes(match[1])) {
- throw new Error('InvalidSelectorStrategy');
- }
- using = match[1];
- value = match[2];
- break;
- }
- case 'xpath': {
- using = 'xpath';
- break;
- }
- case 'id': {
- using = 'id';
- value = stringSelector.slice(3);
- break;
- }
- case 'link text': {
- using = 'link text';
- value = stringSelector.slice(1);
- break;
- }
- case 'partial link text': {
- using = 'partial link text';
- value = stringSelector.slice(2);
- break;
- }
- case '-android uiautomator': {
- using = '-android uiautomator';
- value = stringSelector.slice(8);
- break;
- }
- case '-android datamatcher': {
- using = '-android datamatcher';
- value = JSON.stringify(value);
- break;
- }
- case '-android viewmatcher': {
- using = '-android viewmatcher';
- value = JSON.stringify(value);
- break;
- }
- case '-ios uiautomation': {
- using = '-ios uiautomation';
- value = stringSelector.slice(4);
- break;
- }
- case 'accessibility id': {
- using = 'accessibility id';
- value = stringSelector.slice(1);
- break;
- }
- case 'class name': {
- using = 'class name';
- break;
- }
- case 'tag name': {
- using = 'tag name';
- value = stringSelector.replace(/<|>|\/|\s/g, '');
- break;
- }
- case 'name': {
- if (isMobile || !isW3C) {
- const match = stringSelector.match(/^\[name=("|')([a-zA-z0-9\-_.@=[\] ']+)("|')]$/);
- if (!match) {
- throw new Error(`InvalidSelectorMatch. Strategy 'name' has failed to match '${stringSelector}'`);
- }
- using = 'name';
- value = match[2];
- }
- break;
- }
- case 'xpath extended': {
- using = 'xpath';
- const match = stringSelector.match(new RegExp(XPATH_SELECTOR_REGEXP.map(rx => rx.source).join('')));
- if (!match) {
- throw new Error(`InvalidSelectorMatch: Strategy 'xpath extended' has failed to match '${stringSelector}'`);
- }
- const PREFIX_NAME = { '.': 'class', '#': 'id' };
- const conditions = [];
- const [tag, prefix, name, attrName, attrValue, partial, query] = match.slice(1);
- if (prefix) {
- conditions.push(`contains(@${PREFIX_NAME[prefix]}, "${name}")`);
- }
- if (attrName) {
- conditions.push(attrValue
- ? `contains(@${attrName}, "${attrValue}")`
- : `@${attrName}`);
- }
- conditions.push(partial ? `contains(., "${query}")` : `normalize-space() = "${query}"`);
- value = `.//${tag || '*'}[${conditions.join(' and ')}]`;
- break;
- }
- case '-image': {
- using = '-image';
- value = fs_1.default.readFileSync(stringSelector, { encoding: 'base64' });
- break;
- }
- }
- if (!isMobile && isW3C && !constants_1.W3C_SELECTOR_STRATEGIES.includes(using)) {
- throw new Error('InvalidSelectorStrategy');
- }
- return { using, value };
- };
|