Flexible and powerful element selection system supporting multiple matcher types, combination strategies, and hierarchical relationships for precise UI element targeting.
Core element selection methods using common element properties.
/**
* Select element by test ID or accessibility identifier
* @param id - Test ID string or regular expression pattern
* @returns Matcher for elements with matching test ID
*/
function id(id: string | RegExp): NativeMatcher;
/**
* Select element by visible text content
* @param text - Text string or regular expression pattern
* @returns Matcher for elements containing matching text
*/
function text(text: string | RegExp): NativeMatcher;
/**
* Select element by accessibility label or content description
* @param label - Label string or regular expression pattern
* @returns Matcher for elements with matching accessibility label
*/
function label(label: string | RegExp): NativeMatcher;
/**
* Select element by native view type/class name
* @param nativeViewType - Native view type (e.g., 'RCTImageView', 'Button')
* @returns Matcher for elements of specified type
*/
function type(nativeViewType: string): NativeMatcher;
/**
* Select element by accessibility traits (iOS only)
* @param traits - Array of accessibility trait strings
* @returns Matcher for elements with specified traits
*/
function traits(traits: string[]): NativeMatcher;
/**
* Select element by value attribute
* @param value - Value string to match
* @returns Matcher for elements with matching value
*/
function value(value: string): NativeMatcher;
/**
* Alias for label() - select element by accessibility label
* @param label - Accessibility label string
* @returns Matcher for elements with matching accessibility label
*/
function accessibilityLabel(label: string): NativeMatcher;Usage Examples:
// Select by test ID
await element(by.id('login_button')).tap();
await element(by.id(/submit_.*_button/)).tap(); // Regex pattern
// Select by text content
await element(by.text('Sign In')).tap();
await element(by.text(/^Welcome/)).tap(); // Text starting with "Welcome"
// Select by accessibility label
await element(by.label('Close dialog')).tap();
await element(by.label(/.*menu$/)).tap(); // Label ending with "menu"
// Select by view type
await element(by.type('RCTImageView')).tap();
await element(by.type('android.widget.Button')).tap();
// Select by accessibility traits (iOS)
await element(by.traits(['button', 'selected'])).tap();
// Select by value attribute
await element(by.value('submit')).tap();
// Select by accessibility label (alias for by.label)
await element(by.accessibilityLabel('Close button')).tap();Combine multiple matchers to create more specific element selection criteria.
interface NativeMatcher {
/**
* Combine with another matcher using logical AND
* @param matcher - Additional matcher to combine
* @returns Combined matcher requiring both conditions
*/
and(matcher: NativeMatcher): NativeMatcher;
/**
* Find element with specified ancestor in hierarchy
* @param parentMatcher - Matcher for ancestor element
* @returns Matcher for elements with matching ancestor
*/
withAncestor(parentMatcher: NativeMatcher): NativeMatcher;
/**
* Find element with specified descendant in hierarchy
* @param childMatcher - Matcher for descendant element
* @returns Matcher for elements with matching descendant
*/
withDescendant(childMatcher: NativeMatcher): NativeMatcher;
}Usage Examples:
// Combine multiple conditions
await element(
by.text('Submit').and(by.type('Button'))
).tap();
// Find button inside specific container
await element(
by.id('confirm_button').withAncestor(by.id('dialog_container'))
).tap();
// Find container that has specific child element
await element(
by.type('ScrollView').withDescendant(by.text('Load More'))
).scroll(200, 'down');
// Complex hierarchy selection
await element(
by.id('product_card')
.withDescendant(by.text('iPhone'))
.withAncestor(by.id('products_list'))
).tap();Specialized matchers for elements within web views using DOM-based selection.
/**
* Web element matchers for DOM-based selection
*/
interface ByWebFacade {
/**
* Select by DOM element ID
* @param id - DOM element ID
*/
id(id: string): WebMatcher;
/**
* Select by CSS class name
* @param className - CSS class name
*/
className(className: string): WebMatcher;
/**
* Select by CSS selector
* @param cssSelector - Valid CSS selector string
*/
cssSelector(cssSelector: string): WebMatcher;
/**
* Select by name attribute
* @param name - Element name attribute value
*/
name(name: string): WebMatcher;
/**
* Select by XPath expression
* @param xpath - XPath selector string
*/
xpath(xpath: string): WebMatcher;
/**
* Select link by href attribute
* @param linkText - Complete href value
*/
href(linkText: string): WebMatcher;
/**
* Select link by partial href match
* @param linkTextFragment - Partial href value
*/
hrefContains(linkTextFragment: string): WebMatcher;
/**
* Select by HTML tag name
* @param tagName - HTML tag name
*/
tag(tagName: string): WebMatcher;
/**
* Select by element value (iOS only)
* @param value - Element value
*/
value(value: string): WebMatcher;
/**
* Select by accessibility label (iOS only)
* @param text - Accessibility label text
*/
label(text: string): MaybeSecuredWebMatcher;
/**
* Select secured element by type (iOS only)
* @param type - Element type for secured web elements
*/
type(type: string): SecuredWebMatcher;
}
// Access via by.web
const webMatcher = by.web.id('submit_form');Usage Examples:
// Select web elements by different attributes
await element(web().element(by.web.id('username'))).typeText('user@example.com');
await element(web().element(by.web.className('submit-btn'))).tap();
await element(web().element(by.web.cssSelector('#form .required'))).tap();
await element(web().element(by.web.name('email_field'))).typeText('test@test.com');
await element(web().element(by.web.xpath('//button[@type="submit"]'))).tap();
// Link selection
await element(web().element(by.web.href('https://example.com'))).tap();
await element(web().element(by.web.hrefContains('github.com'))).tap();
// Tag-based selection
await element(web().element(by.web.tag('input'))).typeText('search query');
// iOS secured web elements
await element(web().element(by.web.label('Login').asSecured())).tap();
await element(web().element(by.web.type('textField').asSecured())).typeText('password');Matchers for system-level UI elements outside the app (permissions dialogs, system alerts, etc.).
/**
* System-level element matchers for OS dialogs and alerts
*/
interface BySystemFacade {
/**
* Select system element by label text
* @param text - System element label
*/
label(text: string): SystemMatcher;
/**
* Select system element by type
* @param type - System element type
*/
type(type: string): SystemMatcher;
}
// Access via by.system
const systemMatcher = by.system.label('Allow');Usage Examples:
// Handle permission dialogs
await element(system.element(by.system.label('Allow'))).tap();
await element(system.element(by.system.label('Don\'t Allow'))).tap();
// Interact with system alerts
await element(system.element(by.system.type('button'))).atIndex(1).tap();Recommendations for reliable element selection:
// Best: Explicit test IDs
await element(by.id('login_submit_button')).tap();// Good: Semantic accessibility labels
await element(by.label('Sign in to your account')).tap();// Caution: May break with text changes or localization
await element(by.text('Submit')).tap();// Less reliable: Too generic alone
await element(by.type('Button').and(by.label('Submit'))).tap();Use ancestor/descendant relationships for complex UI structures:
// Select specific button within a form
await element(
by.id('submit_button')
.withAncestor(by.id('registration_form'))
).tap();
// Select list item containing specific text
await element(
by.type('ListItem')
.withDescendant(by.text('John Doe'))
).tap();Use regex patterns for flexible matching:
// Match elements with dynamic IDs
await element(by.id(/^product_\d+_buy_button$/)).tap();
// Match text with variations
await element(by.text(/^Welcome,?\s+\w+/)).tap(); // "Welcome John" or "Welcome, Jane"
// Match partial labels
await element(by.label(/.*Settings$/)).tap(); // Any label ending with "Settings"Handle common selection issues:
// Multiple matches - use index or more specific matcher
try {
await element(by.type('Button')).tap();
} catch (error) {
// More specific selection
await element(by.type('Button').and(by.label('Submit'))).tap();
// Or select by index
await element(by.type('Button')).atIndex(0).tap();
}
// Element not found - wait or verify matcher
await waitFor(element(by.id('dynamic_element')))
.toExist()
.withTimeout(5000);
// Case sensitivity issues
await element(by.text('SUBMIT', { caseSensitive: false })).tap(); // If supported
// Or use regex with case-insensitive flag
await element(by.text(/submit/i)).tap();interface NativeMatcher {
and(matcher: NativeMatcher): NativeMatcher;
withAncestor(parentMatcher: NativeMatcher): NativeMatcher;
withDescendant(childMatcher: NativeMatcher): NativeMatcher;
}
interface WebMatcher {
__web__: any; // Internal marker
}
interface SecuredWebMatcher {
__web__: any; // Internal marker
}
interface MaybeSecuredWebMatcher {
__web__: any; // Internal marker
}
interface SystemMatcher {
__system__: any; // Internal marker
}