Skip to content

Instantly share code, notes, and snippets.

@christian-bromann
Created March 24, 2025 11:29
Show Gist options
  • Save christian-bromann/3d525e86c5dccec9e8171d3a795bc8b4 to your computer and use it in GitHub Desktop.
Save christian-bromann/3d525e86c5dccec9e8171d3a795bc8b4 to your computer and use it in GitHub Desktop.
WebdriverIO Workshop Script for Chapter 13th
interface NodeInfo {
// xpath: string
cssSelector: string
tagName: string
role?: string
name?: string | null
description?: string
isDisabled?: boolean
isAccessible: boolean
children?: NodeInfo[]
attributes?: Record<string, string>
isVisible: boolean
value?: string
textContent?: string
}
declare global {
interface Window {
__wdioDomAccessibilityAPI: {
computeAccessibleDescription: (node: HTMLElement) => string
computeAccessibleName: (node: HTMLElement) => string
getRole: (node: HTMLElement) => string
isDisabled: (node: HTMLElement) => boolean
isInaccessible: (node: HTMLElement) => boolean
isSubtreeInaccessible: (node: HTMLElement) => boolean
}
__wdioGetXPath: (node: HTMLElement) => string
__wdioGetCssSelector: (node: HTMLElement) => string
}
}
export function captureAccessibilityTree(root = document.body) {
// Using native Accessibility APIs
if (!window.getComputedStyle) {
return null
}
/**
* injected via `addInitScript` after session initialization
*/
const {
computeAccessibleDescription,
computeAccessibleName,
getRole,
isDisabled,
isInaccessible,
} = window.__wdioDomAccessibilityAPI
// const getXPath = window.__wdioGetXPath
const getCssSelector = window.__wdioGetCssSelector
function processNode(node: HTMLElement) {
const isVisible = node.checkVisibility({
opacityProperty: true,
visibilityProperty: true,
contentVisibilityAuto: true
})
// const xpath = getXPath(node)
const cssSelector = getCssSelector(node)
const isInaccessibleProp = isInaccessible(node)
const role = getRole(node)
const name = computeAccessibleName(node)
const description = computeAccessibleDescription(node)
const isDisabledProp = isDisabled(node)
/**
* If the node is not visible and not accessible, we can skip it
*/
if (!isVisible && isInaccessibleProp) {
return null
}
// Collect all attributes
const attributes = Array.from(node.attributes)
.reduce((attributes, attr) => {
attributes[attr.name] = attr.value
return attributes
}, {} as Record<string, string>)
// Process child nodes
const children = Array.from(node.children)
.reduce((c, child) => {
const childInfo = processNode(child as HTMLElement)
if (childInfo) {
c.push(childInfo)
}
return c
}, [] as NodeInfo[])
const nodeInfo: NodeInfo = {
// xpath,
cssSelector,
tagName: node.tagName,
isVisible,
isAccessible: !isInaccessibleProp,
...(Object.keys(attributes).length > 0 ? { attributes } : {})
}
const textContent = Array.from(node.childNodes)
.filter((child) => child.nodeType === Node.TEXT_NODE)
.map((child) => child.textContent)
.filter(Boolean)
.join(' ')
if (role) {
nodeInfo.role = role
}
if (name) {
nodeInfo.name = name
}
if (textContent) {
nodeInfo.textContent = textContent
}
if (description) {
nodeInfo.description = description
}
if (children.length > 0) {
nodeInfo.children = children
}
if (isDisabledProp) {
nodeInfo.isDisabled = isDisabledProp
}
if ('value' in node && node.value && typeof node.value === 'string') {
nodeInfo.value = node.value
}
return nodeInfo
}
return processNode(root)
}
import path from 'path'
import url from 'url'
import fs from 'fs/promises'
import type { Services } from '@wdio/types'
// ...
const __dirname = path.dirname(url.fileURLToPath(import.meta.url))
const a11yScript = path.resolve(__dirname, 'thirdParty', 'dom-accessibility-api.js')
const a11yScriptContent = await fs.readFile(a11yScript, 'utf-8')
const getCssSelectorScript = path.resolve(__dirname, 'thirdParty', 'get-css-selector.js')
const getCssSelectorScriptContent = await fs.readFile(getCssSelectorScript, 'utf-8')
export default class ValidationService implements Services.ServiceInstance {
async before (_: never, __: never, browser: WebdriverIO.Browser) {
/**
* register scripts
*/
const contextId = await browser.getWindowHandle()
await Promise.all([
this.#registerScripts(a11yScriptContent, contextId),
this.#registerScripts(getCssSelectorScriptContent, contextId)
])
/**
* add validate command to browser
*/
log.info(`Adding validate command to browser`)
browser.addCommand('validate', this.#validate.bind(this))
}
/**
* Custom command to validate the current state of the application
* @param prompt - The prompt to validate
* @returns nothing, but throws an error if the validation is invalid
*/
async #validate(prompt: string) {
// your implementation
}
/**
* Register a script in the browser for the current context and future page loads
* with the given context.
*
* @param fn - The script to register
* @param contextId - The context to register the script in
* @returns A promise that resolves when the script is registered
*/
#registerScripts (fn: string, contextId: string) {
if (!this.#browser) {
return
}
function handleScriptError (err: unknown) {
const error = err instanceof Error ? err : new Error(`unknown error: ${err}`)
log.error('⚠️ Error adding script', error.message)
}
const functionDeclaration = `${fn}`
return Promise.all([
this.#browser.scriptAddPreloadScript({
functionDeclaration,
contexts: [contextId]
}).catch(handleScriptError),
this.#browser.scriptCallFunction({
functionDeclaration,
target: { context: contextId },
awaitPromise: false
}).catch(handleScriptError)
])
}
}
function domAccessibilityAPIScipt () {var e=Object.prototype.toString;function t(t){return"function"==typeof t||"[object Function]"===e.call(t)}var r=Math.pow(2,53)-1;function n(e){var t=function(e){var t=Number(e);return isNaN(t)?0:0!==t&&isFinite(t)?(t>0?1:-1)*Math.floor(Math.abs(t)):t}(e);return Math.min(Math.max(t,0),r)}function i(e,r){var i=Array,a=Object(e);if(null==e)throw new TypeError("Array.from requires an array-like object - not null or undefined");if(void 0!==r&&!t(r))throw new TypeError("Array.from: when provided, the second argument must be a function");for(var o,u=n(a.length),l=t(i)?Object(new i(u)):new Array(u),d=0;d<u;)o=a[d],l[d]=r?r(o,d):o,d+=1;return l.length=u,l}function a(e){return a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},a(e)}function o(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,u(n.key),n)}}function u(e){var t=function(e,t){if("object"!=a(e)||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t||"default");if("object"!=a(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==a(t)?t:t+""}var l="undefined"==typeof Set?Set:function(){return e=function e(){var t,r,n,i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),t=this,n=void 0,(r=u(r="items"))in t?Object.defineProperty(t,r,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[r]=n,this.items=i},(t=[{key:"add",value:function(e){return!1===this.has(e)&&this.items.push(e),this}},{key:"clear",value:function(){this.items=[]}},{key:"delete",value:function(e){var t=this.items.length;return this.items=this.items.filter((function(t){return t!==e})),t!==this.items.length}},{key:"forEach",value:function(e){var t=this;this.items.forEach((function(r){e(r,r,t)}))}},{key:"has",value:function(e){return-1!==this.items.indexOf(e)}},{key:"size",get:function(){return this.items.length}}])&&o(e.prototype,t),r&&o(e,r),Object.defineProperty(e,"prototype",{writable:!1}),e;var e,t,r}();function d(e){var t;return null!==(t=e.localName)&&void 0!==t?t:e.tagName.toLowerCase()}var c={article:"article",aside:"complementary",button:"button",datalist:"listbox",dd:"definition",details:"group",dialog:"dialog",dt:"term",fieldset:"group",figure:"figure",form:"form",footer:"contentinfo",h1:"heading",h2:"heading",h3:"heading",h4:"heading",h5:"heading",h6:"heading",header:"banner",hr:"separator",html:"document",legend:"legend",li:"listitem",math:"math",main:"main",menu:"list",nav:"navigation",ol:"list",optgroup:"group",option:"option",output:"status",progress:"progressbar",section:"region",summary:"button",table:"table",tbody:"rowgroup",textarea:"textbox",tfoot:"rowgroup",td:"cell",th:"columnheader",thead:"rowgroup",tr:"row",ul:"list"},s={caption:new Set(["aria-label","aria-labelledby"]),code:new Set(["aria-label","aria-labelledby"]),deletion:new Set(["aria-label","aria-labelledby"]),emphasis:new Set(["aria-label","aria-labelledby"]),generic:new Set(["aria-label","aria-labelledby","aria-roledescription"]),insertion:new Set(["aria-label","aria-labelledby"]),none:new Set(["aria-label","aria-labelledby"]),paragraph:new Set(["aria-label","aria-labelledby"]),presentation:new Set(["aria-label","aria-labelledby"]),strong:new Set(["aria-label","aria-labelledby"]),subscript:new Set(["aria-label","aria-labelledby"]),superscript:new Set(["aria-label","aria-labelledby"])};function f(e,t){return function(e,t){return["aria-atomic","aria-busy","aria-controls","aria-current","aria-description","aria-describedby","aria-details","aria-dropeffect","aria-flowto","aria-grabbed","aria-hidden","aria-keyshortcuts","aria-label","aria-labelledby","aria-live","aria-owns","aria-relevant","aria-roledescription"].some((function(r){var n;return e.hasAttribute(r)&&!(null!==(n=s[t])&&void 0!==n&&n.has(r))}))}(e,t)}function b(e){var t=function(e){var t=e.getAttribute("role");if(null!==t){var r=t.trim().split(" ")[0];if(r.length>0)return r}return null}(e);if(null===t||-1!==p.indexOf(t)){var r=function(e){var t=c[d(e)];if(void 0!==t)return t;switch(d(e)){case"a":case"area":case"link":if(e.hasAttribute("href"))return"link";break;case"img":return""!==e.getAttribute("alt")||f(e,"img")?"img":"presentation";case"input":var r=e.type;switch(r){case"button":case"image":case"reset":case"submit":return"button";case"checkbox":case"radio":return r;case"range":return"slider";case"email":case"tel":case"text":case"url":return e.hasAttribute("list")?"combobox":"textbox";case"search":return e.hasAttribute("list")?"combobox":"searchbox";case"number":return"spinbutton";default:return null}case"select":return e.hasAttribute("multiple")||e.size>1?"listbox":"combobox"}return null}(e);if(-1===p.indexOf(t||"")||f(e,r||""))return r}return t}var p=["presentation","none"];function m(e){return null!==e&&e.nodeType===e.ELEMENT_NODE}function v(e){return m(e)&&"caption"===d(e)}function h(e){return m(e)&&"input"===d(e)}function y(e){return m(e)&&"legend"===d(e)}function g(e){return function(e){return m(e)&&void 0!==e.ownerSVGElement}(e)&&"title"===d(e)}function w(e,t){if(m(e)&&e.hasAttribute(t)){var r=e.getAttribute(t).split(" "),n=e.getRootNode?e.getRootNode():e.ownerDocument;return r.map((function(e){return n.getElementById(e)})).filter((function(e){return null!==e}))}return[]}function S(e,t){return!!m(e)&&-1!==t.indexOf(b(e))}function E(e,t){if(!m(e))return!1;if("range"===t)return S(e,["meter","progressbar","scrollbar","slider","spinbutton"]);throw new TypeError("No knowledge about abstract role '".concat(t,"'. This is likely a bug :("))}function x(e,t){var r=i(e.querySelectorAll(t));return w(e,"aria-owns").forEach((function(e){r.push.apply(r,i(e.querySelectorAll(t)))})),r}function A(e){return m(t=e)&&"select"===d(t)?e.selectedOptions||x(e,"[selected]"):x(e,'[aria-selected="true"]');var t}function O(e){return h(e)||m(t=e)&&"textarea"===d(t)?e.value:e.textContent||"";var t}function j(e){var t=e.getPropertyValue("content");return/^["'].*["']$/.test(t)?t.slice(1,-1):""}function N(e){var t=d(e);return"button"===t||"input"===t&&"hidden"!==e.getAttribute("type")||"meter"===t||"output"===t||"progress"===t||"select"===t||"textarea"===t}function P(e){if(N(e))return e;var t=null;return e.childNodes.forEach((function(e){if(null===t&&m(e)){var r=P(e);null!==r&&(t=r)}})),t}function k(e){if(void 0!==e.control)return e.control;var t=e.getAttribute("for");return null!==t?e.ownerDocument.getElementById(t):P(e)}function I(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=new l,n="undefined"==typeof Map?void 0:new Map,a=function(e){var t=(null===e.ownerDocument?e:e.ownerDocument).defaultView;if(null===t)throw new TypeError("no window available");return t}(e),o=t.compute,u=void 0===o?"name":o,c=t.computedStyleSupportsPseudoElements,s=void 0===c?void 0!==t.getComputedStyle:c,f=t.getComputedStyle,b=void 0===f?a.getComputedStyle.bind(a):f,x=t.hidden,P=void 0!==x&&x,I=function(e,t){if(void 0!==t)throw new Error("use uncachedGetComputedStyle directly for pseudo elements");if(void 0===n)return b(e);var r=n.get(e);if(r)return r;var i=b(e,t);return n.set(e,i),i};function L(e,t){var r,n,a="";if(m(e)&&s){var o=j(b(e,"::before"));a="".concat(o," ").concat(a)}if((function(e){return m(e)&&"slot"===d(e)}(e)?0===(n=(r=e).assignedNodes()).length?i(r.childNodes):n:i(e.childNodes).concat(w(e,"aria-owns"))).forEach((function(e){var r=C(e,{isEmbeddedInLabel:t.isEmbeddedInLabel,isReferenced:!1,recursion:!0}),n="inline"!==(m(e)?I(e).getPropertyValue("display"):"inline")?" ":"";a+="".concat(n).concat(r).concat(n)})),m(e)&&s){var u=j(b(e,"::after"));a="".concat(a," ").concat(u)}return a.trim()}function R(e,t){var n=e.getAttributeNode(t);return null===n||r.has(n)||""===n.value.trim()?null:(r.add(n),n.value)}function T(e){if(!m(e))return null;if(function(e){return m(e)&&"fieldset"===d(e)}(e)){r.add(e);for(var t=i(e.childNodes),n=0;n<t.length;n+=1){var a=t[n];if(y(a))return C(a,{isEmbeddedInLabel:!1,isReferenced:!1,recursion:!1})}}else if(function(e){return m(e)&&"table"===d(e)}(e)){r.add(e);for(var o=i(e.childNodes),u=0;u<o.length;u+=1){var l=o[u];if(v(l))return C(l,{isEmbeddedInLabel:!1,isReferenced:!1,recursion:!1})}}else{if(function(e){return m(e)&&"svg"===d(e)}(e)){r.add(e);for(var c=i(e.childNodes),s=0;s<c.length;s+=1){var f=c[s];if(g(f))return f.textContent}return null}if("img"===d(e)||"area"===d(e)){var b=R(e,"alt");if(null!==b)return b}else if(function(e){return m(e)&&"optgroup"===d(e)}(e)){var p=R(e,"label");if(null!==p)return p}}if(h(e)&&("button"===e.type||"submit"===e.type||"reset"===e.type)){var w=R(e,"value");if(null!==w)return w;if("submit"===e.type)return"Submit";if("reset"===e.type)return"Reset"}var E,x,A=null===(x=(E=e).labels)?x:void 0!==x?i(x):N(E)?i(E.ownerDocument.querySelectorAll("label")).filter((function(e){return k(e)===E})):null;if(null!==A&&0!==A.length)return r.add(e),i(A).map((function(e){return C(e,{isEmbeddedInLabel:!0,isReferenced:!1,recursion:!0})})).filter((function(e){return e.length>0})).join(" ");if(h(e)&&"image"===e.type){var O=R(e,"alt");if(null!==O)return O;var j=R(e,"title");return null!==j?j:"Submit Query"}if(S(e,["button"])){var P=L(e,{isEmbeddedInLabel:!1,isReferenced:!1});if(""!==P)return P}return null}function C(e,t){if(r.has(e))return"";if(!P&&function(e,t){if(!m(e))return!1;if(e.hasAttribute("hidden")||"true"===e.getAttribute("aria-hidden"))return!0;var r=t(e);return"none"===r.getPropertyValue("display")||"hidden"===r.getPropertyValue("visibility")}(e,I)&&!t.isReferenced)return r.add(e),"";var n=m(e)?e.getAttributeNode("aria-labelledby"):null,a=null===n||r.has(n)?[]:w(e,"aria-labelledby");if("name"===u&&!t.isReferenced&&a.length>0)return r.add(n),a.map((function(e){return C(e,{isEmbeddedInLabel:t.isEmbeddedInLabel,isReferenced:!0,recursion:!1})})).join(" ");var o,l=t.recursion&&(S(o=e,["button","combobox","listbox","textbox"])||E(o,"range"))&&"name"===u;if(!l){var d=(m(e)&&e.getAttribute("aria-label")||"").trim();if(""!==d&&"name"===u)return r.add(e),d;if(!function(e){return S(e,p)}(e)){var c=T(e);if(null!==c)return r.add(e),c}}if(S(e,["menu"]))return r.add(e),"";if(l||t.isEmbeddedInLabel||t.isReferenced){if(S(e,["combobox","listbox"])){r.add(e);var s=A(e);return 0===s.length?h(e)?e.value:"":i(s).map((function(e){return C(e,{isEmbeddedInLabel:t.isEmbeddedInLabel,isReferenced:!1,recursion:!0})})).join(" ")}if(E(e,"range"))return r.add(e),e.hasAttribute("aria-valuetext")?e.getAttribute("aria-valuetext"):e.hasAttribute("aria-valuenow")?e.getAttribute("aria-valuenow"):e.getAttribute("value")||"";if(S(e,["textbox"]))return r.add(e),O(e)}if(function(e){return S(e,["button","cell","checkbox","columnheader","gridcell","heading","label","legend","link","menuitem","menuitemcheckbox","menuitemradio","option","radio","row","rowheader","switch","tab","tooltip","treeitem"])}(e)||m(e)&&t.isReferenced||function(e){return v(e)}(e)){var f=L(e,{isEmbeddedInLabel:t.isEmbeddedInLabel,isReferenced:!1});if(""!==f)return r.add(e),f}if(e.nodeType===e.TEXT_NODE)return r.add(e),e.textContent||"";if(t.recursion)return r.add(e),L(e,{isEmbeddedInLabel:t.isEmbeddedInLabel,isReferenced:!1});var b=function(e){return m(e)?R(e,"title"):null}(e);return null!==b?(r.add(e),b):(r.add(e),"")}return C(e,{isEmbeddedInLabel:!1,isReferenced:"description"===u,recursion:!1}).trim().replace(/\s\s+/g," ")}function L(e){return L="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},L(e)}function R(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function T(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?R(Object(r),!0).forEach((function(t){C(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):R(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function C(e,t,r){var n;return n=function(e,t){if("object"!=L(e)||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t||"default");if("object"!=L(n))return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(t,"string"),(t="symbol"==L(n)?n:n+"")in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function D(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=w(e,"aria-describedby").map((function(e){return I(e,T(T({},t),{},{compute:"description"}))})).join(" ");if(""===r){var n=e.getAttribute("aria-description");r=null===n?"":n}if(""===r){var i=e.getAttribute("title");r=null===i?"":i}return r}function M(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return S(e,["caption","code","deletion","emphasis","generic","insertion","none","paragraph","presentation","strong","subscript","superscript"])?"":I(e,t)}function V(e){var t,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=r.getComputedStyle,i=void 0===n?null===(t=e.ownerDocument.defaultView)||void 0===t?void 0:t.getComputedStyle:n,a=r.isSubtreeInaccessible,o=void 0===a?q:a;if("function"!=typeof i)throw new TypeError("Owner document of the element needs to have an associated window.");if("hidden"===i(e).visibility)return!0;for(var u=e;u;){if(o(u,{getComputedStyle:i}))return!0;u=u.parentElement}return!1}function q(e){var t,r=(arguments.length>1&&void 0!==arguments[1]?arguments[1]:{}).getComputedStyle,n=void 0===r?null===(t=e.ownerDocument.defaultView)||void 0===t?void 0:t.getComputedStyle:r;if("function"!=typeof n)throw new TypeError("Owner document of the element needs to have an associated window.");return!0===e.hidden||("true"===e.getAttribute("aria-hidden")||"none"===n(e).display)}var z=new Set(["button","fieldset","input","optgroup","option","select","textarea"]);function B(e){var t=d(e);return!(!z.has(t)||!e.hasAttribute("disabled"))||"true"===e.getAttribute("aria-disabled")}
window.__wdioDomAccessibilityAPI = {computeAccessibleDescription: D, computeAccessibleName: M, getRole: b, isDisabled: B, isInaccessible: V, isSubtreeInaccessible: q}}
function getCssSelectorScript () {
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CssSelectorGenerator=e():t.CssSelectorGenerator=e()}(self,(()=>(()=>{"use strict";var t={d:(e,n)=>{for(var r in n)t.o(n,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:n[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};function n(t){return"object"==typeof t&&null!==t&&t.nodeType===Node.ELEMENT_NODE}t.r(e),t.d(e,{default:()=>Q,getCssSelector:()=>K});const r={NONE:"",DESCENDANT:" ",CHILD:" > "},o={id:"id",class:"class",tag:"tag",attribute:"attribute",nthchild:"nthchild",nthoftype:"nthoftype"},i="CssSelectorGenerator";function c(t="unknown problem",...e){console.warn(`${i}: ${t}`,...e)}const u={selectors:[o.id,o.class,o.tag,o.attribute],includeTag:!1,whitelist:[],blacklist:[],combineWithinSelector:!0,combineBetweenSelectors:!0,root:null,maxCombinations:Number.POSITIVE_INFINITY,maxCandidates:Number.POSITIVE_INFINITY};function s(t){return t instanceof RegExp}function a(t){return["string","function"].includes(typeof t)||s(t)}function l(t){return Array.isArray(t)?t.filter(a):[]}function f(t){const e=[Node.DOCUMENT_NODE,Node.DOCUMENT_FRAGMENT_NODE,Node.ELEMENT_NODE];return function(t){return t instanceof Node}(t)&&e.includes(t.nodeType)}function d(t,e){if(f(t))return t.contains(e)||c("element root mismatch","Provided root does not contain the element. This will most likely result in producing a fallback selector using element's real root node. If you plan to use the selector using provided root (e.g. `root.querySelector`), it will not work as intended."),t;const n=e.getRootNode({composed:!1});return f(n)?(n!==document&&c("shadow root inferred","You did not provide a root and the element is a child of Shadow DOM. This will produce a selector using ShadowRoot as a root. If you plan to use the selector using document as a root (e.g. `document.querySelector`), it will not work as intended."),n):S(e)}function m(t){return"number"==typeof t?t:Number.POSITIVE_INFINITY}function p(t=[]){const[e=[],...n]=t;return 0===n.length?e:n.reduce(((t,e)=>t.filter((t=>e.includes(t)))),e)}function g(t){return[].concat(...t)}function h(t){const e=t.map((t=>{if(s(t))return e=>t.test(e);if("function"==typeof t)return e=>{const n=t(e);return"boolean"!=typeof n?(c("pattern matcher function invalid","Provided pattern matching function does not return boolean. It's result will be ignored.",t),!1):n};if("string"==typeof t){const e=new RegExp("^"+t.replace(/[|\\{}()[\]^$+?.]/g,"\\$&").replace(/\*/g,".+")+"$");return t=>e.test(t)}return c("pattern matcher invalid","Pattern matching only accepts strings, regular expressions and/or functions. This item is invalid and will be ignored.",t),()=>!1}));return t=>e.some((e=>e(t)))}function b(t,e,n){const r=Array.from(d(n,t[0]).querySelectorAll(e));return r.length===t.length&&t.every((t=>r.includes(t)))}function y(t,e){e=null!=e?e:S(t);const r=[];let o=t;for(;n(o)&&o!==e;)r.push(o),o=o.parentElement;return r}function N(t,e){return p(t.map((t=>y(t,e))))}function S(t){return t.ownerDocument.querySelector(":root")}const E=", ",v=new RegExp(["^$","\\s"].join("|")),w=new RegExp(["^$"].join("|")),I=[o.nthoftype,o.tag,o.id,o.class,o.attribute,o.nthchild],T=h(["class","id","ng-*"]);function O({name:t}){return`[${t}]`}function C({name:t,value:e}){return`[${t}='${e}']`}function x({nodeName:t,nodeValue:e}){return{name:Y(t),value:Y(null!=e?e:void 0)}}function j(t){const e=Array.from(t.attributes).filter((e=>function({nodeName:t,nodeValue:e},n){const r=n.tagName.toLowerCase();return!(["input","option"].includes(r)&&"value"===t||"src"===t&&(null==e?void 0:e.startsWith("data:"))||T(t))}(e,t))).map(x);return[...e.map(O),...e.map(C)]}function A(t){var e;return(null!==(e=t.getAttribute("class"))&&void 0!==e?e:"").trim().split(/\s+/).filter((t=>!w.test(t))).map((t=>`.${Y(t)}`))}function $(t){var e;const n=null!==(e=t.getAttribute("id"))&&void 0!==e?e:"",r=`#${Y(n)}`,o=t.getRootNode({composed:!1});return!v.test(n)&&b([t],r,o)?[r]:[]}function D(t){const e=t.parentNode;if(e){const r=Array.from(e.childNodes).filter(n).indexOf(t);if(r>-1)return[`:nth-child(${String(r+1)})`]}return[]}function R(t){return[Y(t.tagName.toLowerCase())]}function P(t){const e=[...new Set(g(t.map(R)))];return 0===e.length||e.length>1?[]:[e[0]]}function _(t){const e=P([t])[0],n=t.parentElement;if(n){const r=Array.from(n.children).filter((t=>t.tagName.toLowerCase()===e)),o=r.indexOf(t);if(o>-1)return[`${e}:nth-of-type(${String(o+1)})`]}return[]}function k(t=[],{maxResults:e=Number.POSITIVE_INFINITY}={}){return Array.from(function*(t=[],{maxResults:e=Number.POSITIVE_INFINITY}={}){let n=0,r=M(1);for(;r.length<=t.length&&n<e;){n+=1;const e=r.map((e=>t[e]));yield e,r=L(r,t.length-1)}}(t,{maxResults:e}))}function L(t=[],e=0){const n=t.length;if(0===n)return[];const r=[...t];r[n-1]+=1;for(let t=n-1;t>=0;t--)if(r[t]>e){if(0===t)return M(n+1);r[t-1]++,r[t]=r[t-1]+1}return r[n-1]>e?M(n+1):r}function M(t=1){return Array.from(Array(t).keys())}const V=":".charCodeAt(0).toString(16).toUpperCase(),F=/[ !"#$%&'()\[\]{|}<>*+,./;=?@^`~\\]/;function Y(t=""){return CSS?CSS.escape(t):function(t=""){return t.split("").map((t=>":"===t?`\\${V} `:F.test(t)?`\\${t}`:escape(t).replace(/%/g,"\\"))).join("")}(t)}const W={tag:P,id:function(t){return 0===t.length||t.length>1?[]:$(t[0])},class:function(t){return p(t.map(A))},attribute:function(t){return p(t.map(j))},nthchild:function(t){return p(t.map(D))},nthoftype:function(t){return p(t.map(_))}},q={tag:R,id:$,class:A,attribute:j,nthchild:D,nthoftype:_};function B(t){return t.includes(o.tag)||t.includes(o.nthoftype)?[...t]:[...t,o.tag]}function G(t={}){const e=[...I];return t[o.tag]&&t[o.nthoftype]&&e.splice(e.indexOf(o.tag),1),e.map((e=>{return(r=t)[n=e]?r[n].join(""):"";var n,r})).join("")}function H(t,e,n="",o){const i=function(t,e){return""===e?t:function(t,e){return[...t.map((t=>e+r.DESCENDANT+t)),...t.map((t=>e+r.CHILD+t))]}(t,e)}(function(t,e,n){const r=function(t,e){const{blacklist:n,whitelist:r,combineWithinSelector:o,maxCombinations:i}=e,c=h(n),u=h(r);return function(t){const{selectors:e,includeTag:n}=t,r=[...e];return n&&!r.includes("tag")&&r.push("tag"),r}(e).reduce(((e,n)=>{const r=function(t,e){return(0,W[e])(t)}(t,n),s=function(t=[],e,n){return t.filter((t=>n(t)||!e(t)))}(r,c,u),a=function(t=[],e){return t.sort(((t,n)=>{const r=e(t),o=e(n);return r&&!o?-1:!r&&o?1:0}))}(s,u);return e[n]=o?k(a,{maxResults:i}):a.map((t=>[t])),e}),{})}(t,n),o=function(t,e){return function(t){const{selectors:e,combineBetweenSelectors:n,includeTag:r,maxCandidates:o}=t,i=n?k(e,{maxResults:o}):e.map((t=>[t]));return r?i.map(B):i}(e).map((e=>function(t,e){const n={};return t.forEach((t=>{const r=e[t];r&&r.length>0&&(n[t]=r)})),function(t={}){let e=[];return Object.entries(t).forEach((([t,n])=>{e=n.flatMap((n=>0===e.length?[{[t]:n}]:e.map((e=>Object.assign(Object.assign({},e),{[t]:n})))))})),e}(n).map(G)}(e,t))).filter((t=>t.length>0))}(r,n),i=g(o);return[...new Set(i)]}(t,0,o),n);for(const n of i)if(b(t,n,e))return n;return null}function U(t){return{value:t,include:!1}}function z({selectors:t,operator:e}){let n=[...I];t[o.tag]&&t[o.nthoftype]&&(n=n.filter((t=>t!==o.tag)));let r="";return n.forEach((e=>{var n;(null!==(n=t[e])&&void 0!==n?n:[]).forEach((({value:t,include:e})=>{e&&(r+=t)}))})),e+r}function J(t){return[":root",...y(t).reverse().map((t=>{const e=function(t,e,n=r.NONE){const o={};return e.forEach((e=>{Reflect.set(o,e,function(t,e){return q[e](t)}(t,e).map(U))})),{element:t,operator:n,selectors:o}}(t,[o.nthchild],r.CHILD);return e.selectors.nthchild.forEach((t=>{t.include=!0})),e})).map(z)].join("")}function K(t,e={}){var r;const i=function(t){(t instanceof NodeList||t instanceof HTMLCollection)&&(t=Array.from(t));const e=(Array.isArray(t)?t:[t]).filter(n);return[...new Set(e)]}(t),c=function(t,e={}){const n=Object.assign(Object.assign({},u),e);return{selectors:(r=n.selectors,Array.isArray(r)?r.filter((t=>{return e=o,n=t,Object.values(e).includes(n);var e,n})):[]),whitelist:l(n.whitelist),blacklist:l(n.blacklist),root:d(n.root,t),combineWithinSelector:!!n.combineWithinSelector,combineBetweenSelectors:!!n.combineBetweenSelectors,includeTag:!!n.includeTag,maxCombinations:m(n.maxCombinations),maxCandidates:m(n.maxCandidates)};var r}(i[0],e),s=null!==(r=c.root)&&void 0!==r?r:S(i[0]);let a="",f=s;function p(){return function(t,e,n="",r){if(0===t.length)return null;const o=[t.length>1?t:[],...N(t,e).map((t=>[t]))];for(const t of o){const o=H(t,e,n,r);if(o)return{foundElements:t,selector:o}}return null}(i,f,a,c)}let g=p();for(;g;){const{foundElements:t,selector:e}=g;if(b(i,e,s))return e;f=t[0],a=e,g=p()}return i.length>1?i.map((t=>K(t,c))).join(E):function(t){return t.map(J).join(E)}(i)}const Q=K;return e})()));
window.__wdioGetCssSelector = CssSelectorGenerator.default;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment