Implementation:Webdriverio Webdriverio XPath SelectorBuilder
| Knowledge Sources | |
|---|---|
| Domains | Mobile_Testing, Selector_Optimization |
| Last Updated | 2026-02-12 00:00 GMT |
Overview
The XPath SelectorBuilder constructs optimal native iOS selectors from element data extracted from page source, using a priority-based selection strategy with uniqueness validation.
Description
The buildSelectorFromElementData function takes element data (type and attributes) and attempts to build the most efficient unique selector. The priority order is: (1) Accessibility ID using name or label attributes -- the fastest lookup, (2) Predicate String with progressive attribute addition starting from type and adding meaningful attributes (name, label, value) then boolean attributes (enabled, visible) until uniqueness is achieved, and (3) Class Chain with similar progressive attribute addition. Internal helpers buildUniquePredicateString and buildUniqueClassChain handle the progressive attribute addition strategy, and both skip redundant attributes (e.g., when name equals label). Each candidate selector is validated against the page source using isSelectorUniqueInPageSource.
Usage
This function is called by the XPath converter after it has found an element in the page source via XPath execution, to determine the best native selector for that element.
Code Reference
Source Location
- Repository: Webdriverio_Webdriverio
- File: packages/wdio-appium-service/src/mobileSelectorPerformanceOptimizer/utils/xpath-selector-builder.ts
- Lines: 13-167
Signature
export function buildSelectorFromElementData(
elementData: ElementData,
pageSource: string
): XPathConversionResult | null
Import
import { buildSelectorFromElementData } from './utils/xpath-selector-builder.js'
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| elementData | ElementData |
Yes | Object with type (element node name like 'XCUIElementTypeButton') and attributes (record of all attribute key-value pairs)
|
| pageSource | string |
Yes | Raw XML page source used for uniqueness validation of proposed selectors |
Outputs
| Name | Type | Description |
|---|---|---|
| return | null | Object with selector (the native selector string, or null if no unique selector could be built) and optional warning message (e.g., "Selector may match multiple elements")
|
Usage Examples
Building from Element Data
import { buildSelectorFromElementData } from './xpath-selector-builder.js'
const pageSource = `
<AppiumAUT>
<XCUIElementTypeButton name="Login" label="Login" visible="true" />
<XCUIElementTypeButton name="Cancel" label="Cancel" visible="true" />
</AppiumAUT>`
// Case 1: Unique accessibility ID
const result1 = buildSelectorFromElementData(
{ type: 'XCUIElementTypeButton', attributes: { name: 'Login', label: 'Login', visible: 'true' } },
pageSource
)
// { selector: '~Login' }
// Case 2: Non-unique name, falls to predicate string
const pageSource2 = `
<AppiumAUT>
<XCUIElementTypeButton name="Submit" label="Submit Form" visible="true" />
<XCUIElementTypeStaticText name="Submit" label="Submit" visible="true" />
</AppiumAUT>`
const result2 = buildSelectorFromElementData(
{ type: 'XCUIElementTypeButton', attributes: { name: 'Submit', label: 'Submit Form', visible: 'true' } },
pageSource2
)
// { selector: "-ios predicate string:type == 'XCUIElementTypeButton' AND name == 'Submit'" }
Priority Cascade
// The builder follows this priority:
// 1. Try ~Login (accessibility ID) -> check uniqueness
// 2. If not unique, try -ios predicate string:type == 'XCUIElementTypeButton'
// 3. Add name, label, value attributes progressively until unique
// 4. If predicate still not unique, try -ios class chain:**/XCUIElementTypeButton
// 5. Add attributes progressively until unique
// 6. If nothing works, return best-effort with warning