Automated browser testing for the modern web development stack.
—
TestCafe's Selector API provides powerful DOM element identification and inspection capabilities with CSS and XPath selectors, filtering methods, and automatic waiting for elements to appear.
Create selectors using CSS selectors, XPath expressions, or JavaScript functions.
/**
* Creates a selector for DOM elements
* @param init - CSS selector string, XPath expression, or client function
* @param options - Selector options including dependencies and timeout
* @returns Selector API object with filtering and property access methods
*/
function Selector(init: string | Function, options?: SelectorOptions): SelectorAPI;
interface SelectorOptions {
visibilityCheck?: boolean;
timeout?: number;
boundTestRun?: object;
dependencies?: object;
}
interface SelectorAPI {
(): Promise<NodeSnapshot>;
count: Promise<number>;
exists: Promise<boolean>;
visible: Promise<boolean>;
focused: Promise<boolean>;
textContent: Promise<string>;
innerText: Promise<string>;
value: Promise<string>;
checked: Promise<boolean>;
selected: Promise<boolean>;
selectedIndex: Promise<number>;
id: Promise<string>;
className: Promise<string>;
classNames: Promise<string[]>;
tagName: Promise<string>;
attributes: Promise<object>;
style: Promise<object>;
boundingClientRect: Promise<object>;
hasChildNodes: Promise<boolean>;
hasChildElements: Promise<boolean>;
childElementCount: Promise<number>;
childNodeCount: Promise<number>;
namespaceURI: Promise<string>;
}Usage Examples:
import { Selector } from 'testcafe';
fixture('Selector Examples')
.page('https://example.com');
test('Basic selectors', async t => {
// CSS selector
const submitButton = Selector('#submit-button');
// XPath selector
const linkByText = Selector('//a[contains(text(), "Click here")]');
// Function-based selector
const firstVisibleDiv = Selector(() => {
const divs = document.querySelectorAll('div');
return Array.from(divs).find(div => div.offsetParent !== null);
});
// Use selectors
await t.click(submitButton);
// Access properties
const buttonText = await submitButton.innerText;
const isVisible = await submitButton.visible;
});Filter elements using various criteria including text content, attributes, and position.
/**
* Finds descendant elements matching CSS selector
* @param cssSelector - CSS selector to find within current elements
* @returns New selector with filtered elements
*/
find(cssSelector: string): SelectorAPI;
/**
* Filters elements by text content
* @param text - Exact text string or regular expression to match
* @returns New selector with elements containing matching text
*/
withText(text: string | RegExp): SelectorAPI;
/**
* Filters elements by attribute value
* @param attrName - Attribute name to check
* @param attrValue - Expected attribute value (optional, checks for presence if omitted)
* @returns New selector with elements having matching attribute
*/
withAttribute(attrName: string, attrValue?: string | RegExp): SelectorAPI;
/**
* Filters elements by exact text content
* @param text - Exact text content to match
* @returns New selector with elements having exact text match
*/
withExactText(text: string): SelectorAPI;
/**
* Gets element at specific index
* @param index - Zero-based index of element to select
* @returns New selector for element at specified index
*/
nth(index: number): SelectorAPI;
/**
* Gets first element from selection
* @returns New selector for first element
*/
first(): SelectorAPI;
/**
* Gets last element from selection
* @returns New selector for last element
*/
last(): SelectorAPI;Usage Examples:
test('Element filtering', async t => {
// Find specific elements
const menuItems = Selector('.menu').find('li');
const activeItem = menuItems.withAttribute('class', 'active');
const loginLink = Selector('a').withText('Login');
// Select by position
const firstItem = menuItems.first();
const lastItem = menuItems.last();
const thirdItem = menuItems.nth(2);
// Combine filters
const specificButton = Selector('button')
.withText(/Submit/)
.withAttribute('disabled', false);
await t.click(specificButton);
});Navigate the DOM tree using parent, child, and sibling relationships.
/**
* Gets parent element
* @param cssSelector - Optional CSS selector to filter parent elements
* @returns New selector for parent element(s)
*/
parent(cssSelector?: string): SelectorAPI;
/**
* Gets child elements
* @param cssSelector - Optional CSS selector to filter child elements
* @returns New selector for child element(s)
*/
child(cssSelector?: string): SelectorAPI;
/**
* Gets sibling elements
* @param cssSelector - Optional CSS selector to filter sibling elements
* @returns New selector for sibling element(s)
*/
sibling(cssSelector?: string): SelectorAPI;
/**
* Gets next sibling element
* @param cssSelector - Optional CSS selector to filter next sibling
* @returns New selector for next sibling element
*/
nextSibling(cssSelector?: string): SelectorAPI;
/**
* Gets previous sibling element
* @param cssSelector - Optional CSS selector to filter previous sibling
* @returns New selector for previous sibling element
*/
prevSibling(cssSelector?: string): SelectorAPI;Usage Examples:
test('DOM traversal', async t => {
// Navigate up the DOM
const inputField = Selector('#username');
const formContainer = inputField.parent('form');
const parentDiv = inputField.parent();
// Navigate down the DOM
const table = Selector('#data-table');
const tableRows = table.child('tbody').child('tr');
const firstCell = tableRows.first().child('td').first();
// Navigate across siblings
const currentTab = Selector('.tab.active');
const nextTab = currentTab.nextSibling('.tab');
const prevTab = currentTab.prevSibling('.tab');
await t.click(nextTab);
});Access various DOM element properties and computed styles.
// Properties available on selector instances
interface SelectorAPI {
/** Number of elements matching the selector */
count: Promise<number>;
/** Whether any elements exist */
exists: Promise<boolean>;
/** Whether element is visible */
visible: Promise<boolean>;
/** Whether element has focus */
focused: Promise<boolean>;
/** Element's text content including hidden text */
textContent: Promise<string>;
/** Element's visible text content */
innerText: Promise<string>;
/** Value property for form elements */
value: Promise<string>;
/** Checked state for checkboxes and radio buttons */
checked: Promise<boolean>;
/** Selected state for option elements */
selected: Promise<boolean>;
/** Selected index for select elements */
selectedIndex: Promise<number>;
/** Element's id attribute */
id: Promise<string>;
/** Element's class attribute */
className: Promise<string>;
/** Array of class names */
classNames: Promise<string[]>;
/** Element's tag name */
tagName: Promise<string>;
/** All element attributes as object */
attributes: Promise<{[key: string]: string}>;
/** Computed styles as object */
style: Promise<{[key: string]: string}>;
/** Element's bounding rectangle */
boundingClientRect: Promise<{
left: number;
top: number;
right: number;
bottom: number;
width: number;
height: number;
}>;
}Usage Examples:
test('Element properties', async t => {
const element = Selector('#my-element');
// Check element state
const exists = await element.exists;
const isVisible = await element.visible;
const hasFocus = await element.focused;
// Get text content
const text = await element.innerText;
const fullText = await element.textContent;
// Get form values
const inputValue = await Selector('#username').value;
const isChecked = await Selector('#agree').checked;
// Get element info
const elementId = await element.id;
const classes = await element.classNames;
const tagName = await element.tagName;
// Get computed styles
const styles = await element.style;
const backgroundColor = styles.backgroundColor;
// Get position and size
const rect = await element.boundingClientRect;
console.log(`Element is ${rect.width}x${rect.height} at (${rect.left}, ${rect.top})`);
});Create custom selectors using client-side JavaScript functions.
/**
* Create selector using custom client function
* @param fn - Function to execute in browser context
* @param options - Selector options including dependencies
* @returns Selector API object
*/
function Selector(fn: Function, options?: {
dependencies?: {[key: string]: any};
}): SelectorAPI;Usage Examples:
test('Custom selectors', async t => {
// Select element by computed style
const redElements = Selector(() => {
const elements = document.querySelectorAll('*');
return Array.from(elements).filter(el => {
const style = getComputedStyle(el);
return style.color === 'red' || style.backgroundColor === 'red';
});
});
// Select element with custom logic
const firstVisibleButton = Selector(() => {
const buttons = document.querySelectorAll('button');
return Array.from(buttons).find(button => {
const rect = button.getBoundingClientRect();
return rect.width > 0 && rect.height > 0;
});
});
// Selector with dependencies
const searchTerm = 'testcafe';
const elementWithSearchTerm = Selector((term) => {
const elements = document.querySelectorAll('*');
return Array.from(elements).find(el =>
el.textContent && el.textContent.includes(term)
);
}, { dependencies: { term: searchTerm } });
await t.click(firstVisibleButton);
});Get detailed element information using snapshots.
/**
* Execute selector and return element snapshot
* @returns Promise resolving to detailed element information
*/
(): Promise<NodeSnapshot>;
interface NodeSnapshot {
tagName: string;
attributes: {[key: string]: string};
boundingClientRect: {
left: number;
top: number;
right: number;
bottom: number;
width: number;
height: number;
};
style: {[key: string]: string};
innerText: string;
textContent: string;
namespaceURI: string;
id: string;
className: string;
classNames: string[];
value: any;
checked: boolean;
selected: boolean;
selectedIndex: number;
childElementCount: number;
childNodeCount: number;
hasChildNodes: boolean;
hasChildElements: boolean;
visible: boolean;
focused: boolean;
exists: boolean;
}Usage Examples:
test('Element snapshots', async t => {
const button = Selector('#submit-button');
// Get complete element snapshot
const snapshot = await button();
console.log('Button details:', {
tag: snapshot.tagName,
text: snapshot.innerText,
classes: snapshot.classNames,
position: snapshot.boundingClientRect,
visible: snapshot.visible,
attributes: snapshot.attributes
});
// Use snapshot data in assertions
await t.expect(snapshot.visible).ok();
await t.expect(snapshot.tagName).eql('BUTTON');
});Install with Tessl CLI
npx tessl i tessl/npm-testcafe