Supported Element Resolution Forms in ego-lite: Complete Locator Syntax Guide
ego-lite supports 14 distinct element resolution forms including CSS selectors, XPath expressions, accessibility role locators, text matchers, attribute-based locators, and numeric reference IDs, all parsed through the central parseLocator() function in src/element-resolver.ts.
ego-lite provides a comprehensive element resolution system that enables browser automation agents to target DOM elements through multiple syntaxes. The supported element resolution forms in ego-lite range from standard CSS selectors to specialized accessibility tree queries, all normalized into typed locator objects before resolution. This architecture, implemented in the citrolabs/ego-lite repository, allows test scripts to reference elements via whichever attribute or relationship is most stable for a given application context.
Core Resolution Architecture
The element resolution pipeline centers on src/element-resolver.ts, where the parseLocator() function (starting around line 71) transforms string inputs into structured locator objects. Each locator is normalized to a specific kind value—such as "css", "xpath", "role", "text", or "testid"—before resolution functions like resolveElementCenter() or resolveElementObjectId() convert it into a concrete DOM node, AX node, or execution context reference.
Resolution follows two distinct paths depending on the locator type. Accessibility tree queries (role-based locators) use the Chrome DevTools Protocol (CDP) to fetch AX nodes directly. DOM-based queries (CSS, XPath, text, attributes) inject JavaScript into the page via Runtime.evaluate to return either a box model center for clicks or a JavaScript object ID for further manipulation.
Numeric Reference IDs
The simplest resolution form uses a numeric reference ID generated from previous snapshots.
- Syntax:
@<number>(e.g.,@42) - Implementation: Parsed via
parseRef()insrc/ref-map.ts, which maintains the mapping between numeric refs and Chrome'sbackendNodeId - Use case: Direct reference to elements captured in previous browser states without re-querying the DOM
CSS Selector Locators
ego-lite supports CSS selection through multiple syntax variants.
Raw CSS selectors passed without a prefix are evaluated using document.querySelectorAll via the buildFindElementJs() helper in src/locator-query.ts. The runtime evaluates queryAllExpression() to return matching nodes.
Explicit CSS syntax uses the css: prefix (e.g., css:.nav > a.active). The parser strips this prefix in parseLocator() (lines 73-78) and treats the remainder as a standard CSS locator. This explicit form is required when combining CSS with internal flags like nth.
XPath Expression Locators
XPath selectors provide XML-path-based element targeting.
- Syntax:
xpath:<expression>orxpath=<expression>when combined with nth flags - Implementation:
parseLocator()recognizes the prefix at lines 112-117; resolution occurs throughbuildLocatorFindJs()usingdocument.evaluate - Capability: Supports complex hierarchical queries impossible with CSS selectors alone
Accessibility Role Locators
Role-based locators query the Accessibility (AX) tree rather than the DOM, enabling tests to target elements by their semantic purpose.
- Syntax:
role:<roleName>[name=<name>](e.g.,role:button[name="Submit"]) - Implementation: Parsed at lines 119-125 in
src/element-resolver.ts; resolved via CDP calls tofindBackendNodeIdsByRoleName() - Advantage: Resilient to DOM restructuring when accessibility labels remain consistent
Text and Pattern Matchers
ego-lite includes dedicated locators for matching visible text content and element attributes.
Text Locators match visible text content using fuzzy or exact matching algorithms. The syntax text:<pattern> triggers the textElementsJs() evaluation function (parsed at lines 84-89).
Label Locators match <label> elements or elements with aria-label/aria-labelledby attributes using the label:<pattern> syntax (lines 90-95), evaluated via labelElementsJs().
Placeholder Locators target form inputs by their placeholder text using placeholder:<pattern> (lines 96-101), evaluated through attributeElementsJs().
Alt Text Locators match images and inputs by their alt attribute using alt:<pattern> (lines 102-107).
Title Locators find elements by their title attribute using title:<pattern> (lines 108-113).
Test ID Locators provide a testing-specific hook via testid:<pattern>, matching the data-testid attribute (lines 114-119).
Href Locators
The href locator finds anchor elements by their resolved URL path rather than DOM position.
- Syntax:
href:<path>(e.g.,href:/settings/account) - Implementation: Parsed at lines 77-82 in
parseLocator(); evaluated viahrefElementsJs() - Behavior: Resolves the full URL before matching, handling relative paths correctly
The Loc= Prefix Convention
ego-lite recognizes a special loc= prefix used to explicitly denote locator strings. When parseLocator() detects that a value starts with "loc=" (line 71), it strips this prefix before proceeding with standard parsing. This convention appears in loc=css:button.primary or loc=role:button[name="Submit"] syntaxes, providing explicit signaling for locator types in complex command chains.
Internal Resolution Modifiers
Advanced resolution uses internal flags to modify how other locator forms behave.
Nth and Last Flags force selection of a specific match index. The syntax internal:nth=<n>;<locator> or internal:last;<locator> (parsed at lines 17-26) selects the nth or final match from any locator type's result set.
Scope and Query Flags provide generic query containers for advanced internal uses. The forms internal:scope:<expr> and internal:filter:<expr> (lines 31-33) create untyped query locators used by ego-lite's internal helper functions.
Error Handling and Retry Semantics
The resolver distinguishes between transient failures (element not yet rendered) and permanent failures (ambiguous selector) through the ElementResolutionError.kind property. This distinction enables higher-level helpers in src/helpers.ts (the public API surface for click, hover, type, etc.) to implement intelligent retry loops for timing-related resolution failures.
Code Examples
// Numeric reference from snapshot
await ego.click("@42");
// Raw CSS selector
await ego.click("button.submit");
// Explicit CSS syntax
await ego.click("css:.nav > a.active");
// XPath with nth modifier
await ego.click("internal:nth=2;xpath=//div[@data-id='item']");
// Accessibility role with name
await ego.click("role:button[name='Submit']");
// Fuzzy text matching
await ego.click("text:Sign in");
// Exact text matching
await ego.click("text:exact:\"Welcome back\"");
// Label association
await ego.click("label:Search");
// Placeholder text
await ego.click("placeholder:Enter email");
// Alt attribute on images
await ego.click("alt:Company logo");
// Title attribute
await ego.click("title:Help");
// Data-testid attribute
await ego.click("testid:login-button");
// Href path matching
await ego.click("href:/settings/account");
// Internal scope query
await ego.click("internal:scope:div[role='dialog']");
Summary
- ego-lite resolves elements through 14 distinct locator forms defined in
src/element-resolver.ts, ranging from@refIDs to complex XPath expressions. - The central parser
parseLocator()normalizes all inputs into typedkindobjects before resolution via either CDP (for accessibility roles) or JavaScript injection (for DOM queries). - Attribute-based locators (text, label, placeholder, alt, title, testid) use
attributeElementsJs()for consistent pattern matching against element properties. - Internal modifiers (
internal:nth,internal:last) provide result-set filtering capabilities applicable to any base locator type. - The system implements intelligent error classification through
ElementResolutionError, enabling automatic retries for transient resolution failures.
Frequently Asked Questions
What is the difference between raw CSS selectors and the css: prefix in ego-lite?
Raw CSS selectors (e.g., div.article > a) are evaluated directly through querySelectorAll without prefix stripping, while the css: prefix explicitly signals a CSS locator type and is required when combining CSS with internal flags like nth. According to the source code in src/element-resolver.ts lines 73-78, the parser strips the prefix to normalize both forms into the same internal representation.
How does ego-lite handle element resolution for accessibility testing?
ego-lite provides first-class support for accessibility tree queries through the role: locator syntax, implemented at lines 119-125 of src/element-resolver.ts. Unlike DOM-based locators that use JavaScript injection, role locators communicate directly with the browser's Accessibility tree via Chrome DevTools Protocol calls to findBackendNodeIdsByRoleName(), making them resilient to DOM restructuring while respecting semantic meaning.
Can ego-lite resolve elements that are not yet visible in the DOM?
Yes, the resolver distinguishes between transient and permanent resolution failures through the ElementResolutionError.kind property. Transient failures—such as elements not yet rendered or added to the DOM—trigger automatic retry loops in the helper functions defined in src/helpers.ts, while permanent failures (ambiguous selectors, invalid syntax) fail immediately.
Where is the documentation for supported locator forms generated in the codebase?
The runtime documentation returned by ego-lite's help() function is generated from JSDoc comments parsed in src/help-runtime.ts. This module dynamically constructs help text documenting all supported element resolution forms, ensuring the documentation stays synchronized with the actual implementation in src/element-resolver.ts and related resolver modules.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →