Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:DevExpress Testcafe Selector API

From Leeroopedia
Knowledge Sources
Domains Testing, Web_Automation
Last Updated 2026-02-12 04:00 GMT

Overview

Concrete implementation of selector filtering and traversal in TestCafe through the `addAPI()` function, which decorates Selector instances with chainable methods and properties for DOM navigation and element property access.

Description

The `addAPI()` function dynamically adds a comprehensive set of filtering, traversal, and property access methods to Selector instances. These methods enable complex DOM queries through method chaining, with each method returning a new Selector. Property accessors return promises that resolve to element values. All methods are automatically available on Selector instances without requiring separate imports.

Usage

Use Selector API methods to refine selections and navigate the DOM. Chain methods to build complex queries. Access properties to extract element information for assertions.

Code Reference

Source Location

  • Repository: testcafe
  • File: src/client-functions/selectors/add-api.js
  • Lines: 1-802

Signature

// Filtering methods
selector.nth(index: number): Selector
selector.withText(text: string | RegExp): Selector
selector.withExactText(text: string): Selector
selector.withAttribute(name: string, value?: string | RegExp): Selector
selector.filter(cssSelector: string | Function, dependencies?: object): Selector
selector.filterVisible(): Selector
selector.filterHidden(): Selector

// Traversal methods
selector.find(cssSelector: string | Function, dependencies?: object): Selector
selector.parent(index?: number | cssSelector?: string | Function): Selector
selector.child(index?: number | cssSelector?: string | Function): Selector
selector.sibling(index?: number | cssSelector?: string | Function): Selector
selector.nextSibling(index?: number | cssSelector?: string | Function): Selector
selector.prevSibling(index?: number | cssSelector?: string | Function): Selector

// Property accessors (return promises)
selector.count: Promise<number>
selector.exists: Promise<boolean>
selector.visible: Promise<boolean>
selector.innerText: Promise<string>
selector.textContent: Promise<string>
selector.value: Promise<string>
selector.checked: Promise<boolean>
selector.tagName: Promise<string>
selector.id: Promise<string>
selector.classNames: Promise<string[]>
selector.attributes: Promise<object>
selector.style: Promise<object>
selector.boundingClientRect: Promise<object>

Import

// Methods automatically available on Selector instances
import { Selector } from 'testcafe';

const selector = Selector('.item');
// All API methods are available immediately
selector.nth(0).visible;

I/O Contract

Inputs

Name Type Required Description
index number Varies Zero-based index for nth(), child(), sibling() methods
text RegExp Varies Text content to filter by in withText() and withExactText()
name string Yes (for withAttribute) Attribute name to filter by
value RegExp No Attribute value to match (optional for existence check)
cssSelector Function Varies CSS selector or filter function for filter(), find(), parent(), child(), sibling()
dependencies object No Variables to inject into filter/find functions

Outputs

Name Type Description
selector Selector New selector instance with refined selection (for methods)
value Promise<T> Promise resolving to property value (for properties)

Usage Examples

Index Filtering with nth()

import { Selector } from 'testcafe';

fixture`Filtering`
  .page`https://example.com`;

test('Select by index', async t => {
  const items = Selector('.list-item');
  const firstItem = items.nth(0);
  const thirdItem = items.nth(2);

  await t
    .expect(firstItem.textContent).contains('First')
    .click(thirdItem);
});

Text Filtering

import { Selector } from 'testcafe';

test('Filter by text', async t => {
  const buttons = Selector('button');
  const submitButton = buttons.withText('Submit');
  const deleteButton = buttons.withExactText('Delete');
  const saveButtons = buttons.withText(/^Save/);

  await t
    .click(submitButton)
    .expect(deleteButton.visible).ok();
});

Attribute Filtering

import { Selector } from 'testcafe';

test('Filter by attribute', async t => {
  const inputs = Selector('input');
  const requiredInputs = inputs.withAttribute('required');
  const emailInput = inputs.withAttribute('type', 'email');
  const placeholderPattern = inputs.withAttribute('placeholder', /Enter/);

  const count = await requiredInputs.count;
  await t.expect(count).gt(0);
});

Custom Filter Function

import { Selector } from 'testcafe';

test('Custom filter', async t => {
  const products = Selector('.product');
  const expensiveProducts = products.filter(node => {
    const price = parseFloat(node.querySelector('.price').textContent);
    return price > 100;
  });

  await t.expect(expensiveProducts.count).gt(0);
});

DOM Traversal

import { Selector } from 'testcafe';

test('Navigate DOM', async t => {
  const checkbox = Selector('input[type="checkbox"]').withAttribute('id', 'agree');
  const label = checkbox.parent('label');
  const container = checkbox.parent('.form-group');
  const helpText = checkbox.nextSibling('.help-text');

  // Click label to toggle checkbox
  await t
    .click(label)
    .expect(checkbox.checked).ok();
});

Finding Descendants

import { Selector } from 'testcafe';

test('Find descendants', async t => {
  const form = Selector('#registration-form');
  const submitButton = form.find('button[type="submit"]');
  const inputs = form.find('input');

  await t
    .expect(inputs.count).eql(5)
    .click(submitButton);
});

Property Access

import { Selector } from 'testcafe';

test('Access properties', async t => {
  const heading = Selector('h1');
  const input = Selector('#username');
  const checkbox = Selector('#terms');

  // Properties return promises
  const headingText = await heading.innerText;
  const inputValue = await input.value;
  const isChecked = await checkbox.checked;
  const isVisible = await heading.visible;
  const elementCount = await Selector('.item').count;

  await t
    .expect(headingText).contains('Welcome')
    .expect(elementCount).gte(3);
});

Complex Chaining

import { Selector } from 'testcafe';

test('Chain multiple operations', async t => {
  // Find the third visible product card with "Sale" badge,
  // then find its Add to Cart button
  const saleProducts = Selector('.product-card')
    .filterVisible()
    .withText('Sale');

  const thirdSaleProduct = saleProducts.nth(2);
  const addToCartButton = thirdSaleProduct.find('button.add-to-cart');

  await t.click(addToCartButton);
});

Visibility Filtering

import { Selector } from 'testcafe';

test('Filter by visibility', async t => {
  const allModals = Selector('.modal');
  const visibleModals = allModals.filterVisible();
  const hiddenModals = allModals.filterHidden();

  await t
    .expect(visibleModals.count).eql(1)
    .expect(hiddenModals.count).gte(0);
});

Related Pages

Implements Principle

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment