/** * Stable attributes are attributes that are commonly used to identify parts of a UI (ex: * component). Those attribute values should not be generated randomly (hardcoded most of the time) * and stay the same across deploys. They are not necessarily unique across the document. */ export declare const STABLE_ATTRIBUTES: string[]; export declare function getSelectorFromElement(targetElement: Element, actionNameAttribute: string | undefined): string | undefined; /** * Check whether the selector is unique among the element siblings. In other words, it returns true * if "ELEMENT_PARENT > CHILD_SELECTOR" returns a single element. * * @param currentElement - the element being considered while iterating over the target * element ancestors. * @param currentElementSelector - a selector that matches the current element. That * selector is not a composed selector (i.e. it might be a single tag name, class name...). * @param childSelector - child selector is a selector that targets a descendant * of the current element. When undefined, the current element is the target element. * * # Scope selector usage * * When composed together, the final selector will be joined with `>` operators to make sure we * target direct descendants at each level. In this function, we'll use `querySelector` to check if * a selector matches descendants of the current element. But by default, the query selector match * elements at any level. Example: * * ```html *
*
* *
* *
* *
*
*
* ``` * * `sibling.querySelector('DIV > SPAN')` will match both span elements, so we would consider the * selector to be not unique, even if it is unique when we'll compose it with the parent with a `>` * operator (`MAIN > DIV > SPAN`). * * To avoid this, we can use the `:scope` selector to make sure the selector starts from the current * sibling (i.e. `sibling.querySelector('DIV:scope > SPAN')` will only match the first span). * * [1]: https://developer.mozilla.org/fr/docs/Web/CSS/:scope * * # Performance considerations * * We compute selectors in performance-critical operations (ex: during a click), so we need to make * sure the function is as fast as possible. We observed that naively using `querySelectorAll` to * check if the selector matches more than 1 element is quite expensive, so we want to avoid it. * * Because we are iterating the DOM upward and we use that function at every level, we know the * child selector is already unique among the current element children, so we don't need to check * for the current element subtree. * * Instead, we can focus on the current element siblings. If we find a single element matching the * selector within a sibling, we know that it's not unique. This allows us to use `querySelector` * (or `matches`, when the current element is the target element) instead of `querySelectorAll`. */ export declare function isSelectorUniqueAmongSiblings(currentElement: Element, currentElementSelector: string, childSelector: string | undefined): boolean;