Selector Recipes

This article contains code examples for simple Selector use cases. Before you read this article, read the Selectors guide to learn how Selectors work.

Use Selectors in Actions

Use Selectors to specify targets for test actions:

import { Selector } from 'testcafe';

fixture `My fixture`
    .page `http://devexpress.github.io/testcafe/example/`;

const label = Selector('#tried-section').child('label');

test('My Test', async t => {
    await t.click(label);
});

Use Selectors in Assertions

Use Selectors to specify assertion targets. Selectors in assertions are subject to the Smart Assertion Query Mechanism.

import { Selector } from 'testcafe';

fixture `My fixture`
    .page `http://devexpress.github.io/testcafe/example/`;

test('Assertion with Selector', async t => {
    const developerNameInput = Selector('#developer-name');

    await t
        .expect(developerNameInput.value).eql('')
        .typeText(developerNameInput, 'Peter')
        .expect(developerNameInput.value).eql('Peter');
});

Use Selectors to Check if an Element Exists

Use the following properties to check whether your Selector query matches a page element:

Property Type Description
exists Boolean true if at least one matching element exists.
count Number The number of matching elements.

Selector property getters are asynchronous.

import { Selector } from 'testcafe';

fixture `Example page`
    .page `http://devexpress.github.io/testcafe/example/`;

test('My test', async t => {
    const osCount            = Selector('.column.col-2 label').count;
    const submitButtonExists = Selector('#submit-button').exists;

    await t
        .expect(osCount).eql(3)
        .expect(submitButtonExists).ok();
});

Conditionals make tests unreliable and unpredictable. A good rule of thumb is to avoid conditionals at all costs.

However, some websites warrant the use of conditionals. If you’re unsure that your action target is visible, you may check its visibility status:

import { Selector } from 'testcafe';

fixture `My fixture`
    .page `https://devexpress.github.io/testcafe/example/`;

test('My test', async t => {
    const element = Selector('#developer-name');

    if(await element.exists && await element.visible)
        await t.typeText(element, 'Peter Parker');

    // ...
});

Examine DOM Elements (DOM Node Snapshot)

When you asynchronously execute a Selector query, it returns a DOM Node Snapshot object with the results of the query and their properties.

If a Selector matches several DOM nodes, the query only returns the first matching node.

You can use this object to examine the state of the DOM element:

import { Selector } from 'testcafe';

fixture `My fixture`
    .page `http://devexpress.github.io/testcafe/example/`;

test('DOM Node State', async t => {
    const sliderHandle         = Selector('#slider').child('span');
    const sliderHandleSnapshot = await sliderHandle();

    console.log(sliderHandleSnapshot.hasClass('ui-slider-handle'));    // => true
    console.log(sliderHandleSnapshot.childElementCount);               // => 0
});

The DOM Node State API contains methods that let you access the properties of the query result:

const headerText = await Selector('#header').textContent;

You can save the snapshot to a variable and pass this variable to actions. See Selector-based Selectors for more information.

import { Selector } from 'testcafe';

fixture `My fixture`
    .page `http://devexpress.github.io/testcafe/example/`;

const label = Selector('#tried-section').child('label');

test('My Test', async t => {
    const labelSnapshot = await label();

    await t.click(labelSnapshot);
});

Note

The Smart Assertion Query Mechanism does not apply to assertions that examine a DOM Node Snapshot. Pass a Selector query to the assertion to take advantage of the Smart Assertion Query Mechanism.

Access Custom Element Properties

Use the selector.addCustomDOMProperties Selector method to retrieve custom element properties from the DOM.

import { Selector } from 'testcafe';

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

test('Check Label HTML', async t => {
    const label = Selector('label').addCustomDOMProperties({
        innerHTML: el => el.innerHTML,
        tabIndex: el => el.tabIndex,
        lang: el => el.lang
    });

    await t
        .expect(label.innerHTML).contains('type="checkbox"')
        .expect(label.tabIndex).eql(2)
        .expect(label.lang).eql('en');
});

Obtain the property with a client function. Pass the selector to the dependencies option:

import { Selector, ClientFunction } from 'testcafe';

fixture `My fixture`
    .page `https://devexpress.github.io/testcafe/example/`;

test('Check Label HTML', async t => {
    const label = Selector('label');

    const getLabelHtml = ClientFunction(() => label().innerHTML, { dependencies: { label } });

    await t
        .expect(getLabelHtml()).contains('type="checkbox"')
        .expect(getLabelHtml()).contains('name="remote"');
});

Note

Client functions and selector property getters are asynchronous, and require the await keyword.

However, the asynchronous Smart Assertion Query Mechanism lets you omit the await keyword when you pass a client function or a selector property to an assertion.

Access non-element nodes

TestCafe includes three Selector methods that can return non-element nodes: filter(function), find and parent. All other methods only return DOM elements.

Consider the following example.html page:

<!DOCTYPE html>
<html>
    <body>
        This is my page. <!--This is the first child node of <body>-->
        <p>My first paragraph.</p>
        <p>My second paragraph.</p>
    </body>
</html>

The first sentence on the page is not a DOM element.

To select this node, we need to use the find method. In contrast, the child method skips the text node and returns the <p> element.

import { Selector } from 'testcafe';

fixture `My Fixture`
    .page `example.html`;

const body              = Selector('body');
const firstChildElement = body.child(0);                 // <p>
const firstChildNode    = body.find((node, index) => {   // text node
    return index === 0;
});

test('My Test', async t => {
    await t
        .expect(firstChildElement.textContent).eql('My first paragraph.')
        .expect(firstChildNode.textContent).eql('\n        This is my page. ');
});

Select Elements That Contain Special Characters

Replace HTML symbols and entities (for example, &nbsp; or \n) with their unicode counterparts when you use Selector.WithText or Selector.WithExactText to filter the page.

Example

<html>
    <body>
        <p>Click&nbsp;me</p>
    </body>
</html>
import { Selector } from 'testcafe';

fixture `My fixture`
    .page `http://localhost/`;

test('My test', async t => {
    const sel = await Selector('p').withText('Click&nbsp;me') //typed representation, not supported
    const sel = await Selector('p').withText('Click\u00a0me') //unicode representation, works
    const sel = await Selector('p').withText('Click\xa0me') //hexadecimal representation, works
    const sel = await Selector('p').withText('Click\160me') //decimal representation introduced with an octal escape sequence;
                                                            // not supported because tests are executed in strict mode
});

Important

Strict mode JavaScript prohibits the use of octal escape sequences in strings.