UNPKG

testcafe-selector-generator

Version:
93 lines (74 loc) 3.64 kB
import TESTCAFE_CORE from '../../deps/testcafe-core'; import { escapeSpecifiedSymbols, escapeValueForSelectorWithRegExp, escapeAttrValue, } from '../utils/escape'; import { SelectorDescriptor } from '../../selector-descriptor'; import { FilterOption } from '../../selector-descriptor/filter-option'; import * as FILTER_OPTION_TYPE from '../../selector-descriptor/filter-option-type'; import { getAttributeRegExpFilter } from '../../selector-descriptor/filters'; const { domUtils, arrayUtils } = TESTCAFE_CORE; const ASP_AUTOGENERATED_ATTR_RE = /\$ctl\d+|ctl\d+\$|_ctl\d+|ctl\d+_|^ctl\d+$/g; const SEPARATOR_CONST = '!!!!!separator!!!!!'; const ANY_NUMBER_CONST = '!!!!!anyNumber!!!!!'; const SEPARATOR_RE = new RegExp(SEPARATOR_CONST, 'g'); const ANY_NUMBER_RE = new RegExp(ANY_NUMBER_CONST, 'g'); const SOME_SPACES_RE = /\s{2,}/g; const MAX_TEXT_LENGTH_IN_SELECTOR = 50; export const CLASS_ATTRIBUTE_NAME = 'class'; // eslint-disable-next-line max-params export function getRegExpAttributesDescriptor (ruleType, el, cssSelector, filterRegExpValue, ancestorSelectorDescriptor) { return new SelectorDescriptor({ ancestorSelectorDescriptor: ancestorSelectorDescriptor, cssSelector: cssSelector, element: el, filter: getAttributeRegExpFilter(filterRegExpValue), filterOptions: new FilterOption(FILTER_OPTION_TYPE.byAttr, filterRegExpValue), ruleType: ruleType, }); } // eslint-disable-next-line max-lines-per-function, max-params export function getAttributesDescriptor (ruleType, el, attributes, ancestorSelectorDescriptor) { const tagName = domUtils.getTagName(el); let cssSelector = ''; let attrRegExpObject = null; arrayUtils.forEach(attributes, ({ name, value }) => { let valueWasCut = false; let shouldUseRegExp = false; if (value.replace(SOME_SPACES_RE, ' ').length > MAX_TEXT_LENGTH_IN_SELECTOR) { value = value.substr(0, MAX_TEXT_LENGTH_IN_SELECTOR); valueWasCut = true; } if (ASP_AUTOGENERATED_ATTR_RE.test(value)) { shouldUseRegExp = true; value = value.replace(ASP_AUTOGENERATED_ATTR_RE, substr => substr.replace(/\d+/, ANY_NUMBER_CONST)); } if (SOME_SPACES_RE.test(value)) { shouldUseRegExp = true; value = value.replace(SOME_SPACES_RE, SEPARATOR_CONST); } if (shouldUseRegExp) { if (!attrRegExpObject) { value = escapeValueForSelectorWithRegExp(value); value = value.replace(ANY_NUMBER_RE, '\\d+').replace(SEPARATOR_RE, '\\s+'); attrRegExpObject = { attrName: name, attrValueRe: new RegExp(value) }; } } else { value = name === CLASS_ATTRIBUTE_NAME ? escapeSpecifiedSymbols(value).trimEnd() : escapeAttrValue(value); if (name === CLASS_ATTRIBUTE_NAME && !valueWasCut) cssSelector += (' ' + value).replace(/\s+/g, '.'); else cssSelector += `[${name}${valueWasCut ? '^' : ''}${value ? `="${value}"` : ''}]`; } }); if (attrRegExpObject) { const selector = cssSelector || tagName; return getRegExpAttributesDescriptor(ruleType, el, selector, attrRegExpObject, ancestorSelectorDescriptor); } return new SelectorDescriptor({ ruleType, element: el, ancestorSelectorDescriptor, cssSelector, }); }