# Supported Element Resolution Forms in ego-lite: Complete Locator Syntax Guide

> Discover ego-lite's 14 element resolution forms, including CSS selectors, XPath, and text matchers. Master locator syntax with our complete guide.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: api-reference
- Published: 2026-08-27

---

**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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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()` in **[`src/ref-map.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/ref-map.ts)**, which maintains the mapping between numeric refs and Chrome's `backendNodeId`
- **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`](https://github.com/citrolabs/ego-lite/blob/main/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>` or `xpath=<expression>` when combined with nth flags
- **Implementation**: `parseLocator()` recognizes the prefix at lines 112-117; resolution occurs through `buildLocatorFindJs()` using `document.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`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts); resolved via CDP calls to `findBackendNodeIdsByRoleName()`
- **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 via `hrefElementsJs()`
- **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`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts)** (the public API surface for `click`, `hover`, `type`, etc.) to implement intelligent retry loops for timing-related resolution failures.

## Code Examples

```javascript
// 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`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts), ranging from `@ref` IDs to complex XPath expressions.
- The **central parser** `parseLocator()` normalizes all inputs into typed `kind` objects 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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/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`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) and related resolver modules.