Element Selectors

  • 15 minutes to read

Actions and assertions use Selector queries to locate their targets.

Selectors filter the DOM and return page elements that match user-defined criteria. They are similar to CSS Selectors in both purpose and syntax.

The Anatomy of Element Selectors

Every Selector query begins with an invocation of the Selector() constructor. The initial results of the Selector query depend on the arguments that you pass to the Selector constructor.

There are three ways to initialize a Selector. In this example, we used a CSS Keyword:

Selector('#big-red-button');

Selector methods perform additional actions with the initial results of the Selector query.

Selector('button').withText('click me');

Simple Selectors and Compound Selectors

Simple Selectors filter the DOM once:

Selector('#big-red-button');

Compound Selectors filter the DOM multiple times:

Selector('nav .button');
// or 
Selector('nav').find('.button')

The example above matches button class elements that reside inside nav blocks.

Selector Types

Keyword-Based Selectors

Keyword-Based Selectors filter the page in search of elements that match CSS keywords.

Selector('#some-element');

A few examples:

  • body matches the body element.
  • .login matches elements with the login class name.
  • #input matches elements with the input ID.

Selector Keywords

TestCafe Selector keywords are syntactically identical to CSS Selectors. TestCafe actions can’t target pseudo-elements and require additional code to target the Shadow DOM.

Top Tip: Use Custom HTML Attributes

Keywords that reference custom HTML attributes are more reliable, because they don’t reference mutable code.

  • Selectors break when you change the page code that they reference.
  • Bad Selectors reference class names or DOM relationships – things that change fairly often during development.
  • Reliable Selectors reference properties that are independent of page design and layout.

Mark your actions’ targets with custom HTML attributes, and generate better, more reliable Selectors.

  1. Add a custom HTML attribute (for example: data-test-id) to all the page elements that your test interacts with.
  2. Assign meaningful values to these custom attributes.
  3. Add your attribute to the Selector Components list. When TestCafe Studio generates Selector queries, it uses custom attributes from the Selector Components list.
  4. Reference your attribute when you write Selector queries (test scripts only):
t.click('button').withAttribute('data-test-id','left-button')

Function-based Selectors

Function-based Selectors execute a client-side function that traverses the DOM and returns one of the following objects:

  • A DOM node
  • An array of DOM nodes
  • A NodeList object
  • An HTMLCollection object
  • A null object
  • An undefined object

The function-based Selector below retrieves a string from localStorage and finds a DOM element with the identical ID:

const element = Selector(() => {
    const storedElementId = window.localStorage.storedElementId;
    return document.getElementById(storedElementId);
});

Function-based Selectors can have additional parameters:

const elementWithId = Selector(id => {
    return document.getElementById(id);
});

await t.click(elementWithId('buy'));

Selector-Based Selectors

You can create Selectors based on other Selectors. These copies inherit original Selectors’ queries, but do not inherit their return value.

The example code below creates a copy of the ctaButton Selector with a modified visibilityCheck option:

const ctaButton = Selector('.cta-button');
Selector(ctaButton, { visibilityCheck: true });

You can create a new Selector from a DOM Node Snapshot object returned by another Selector. These Selectors inherit the original Selector’s return value, but you can still override their options:

const topMenuSnapshot = await Selector('#top-menu')();
const visibleTopMenu = Selector(topMenuSnapshot, {
        visibilityCheck: true
    });

You can create a new Selector from a Selector Promise:

const elementWithIdOrClassName = Selector(value => {
    return document.getElementById(value) || document.getElementsByClassName(value);
});
const submitButton = Selector(elementWithIdOrClassName('main-element'));

Selector Options

You can customize the behavior of Selectors with constructor options (test scripts only).

Selector Methods

Selector methods perform additional actions with the return value of the main Selector query. Selector methods narrow, expand, or otherwise modify the selection of page elements.

Selector('keyword1 keyword2').method1().method2();

Filter Methods

Filter methods filter the page element selection.

nth(index)

Finds the element with the specified index. The index starts at 0. Negative index values indicate the element’s location relative to the final element of the array.

For example:

  • nth(2) - Selects the third element.
  • nth(-1) - Selects the last element.

withText(string)

Finds elements with a textContent value that contains the specified string (case-sensitive).

To find elements with a specific textContent value, use the withExactText method.

withText(re)

Finds elements with a textContent value that matches the specified regular expression.

Example: withText(/a[b-e]/).

withExactText(string)

Finds elements with a textContent value equal to the specified string (case-sensitive).

To find elements that contain a specific string, use the withText method.

withAttribute(attrName)

Finds elements with the specified attribute, regardless of that attribute’s value.

The method accepts both strings and regular expressions.

For example, withAttribute(‘myAttr’) matches elements that have the myAttr attribute.

withAttribute(attrName, attrValue)

Finds elements with an attribute of specific value.

The method accepts both strings and regular expressions.

For example, withAttribute(‘foo’, /a[0-9]/) returns elements that have a foo attribute with a value that matches the /a[0-9]/ regular expression (‘a7’ or ‘a0’).

filterVisible()

Finds visible elements.

TestCafe considers an element visible if:

  • The value of the element’s display property is not none
  • The value of the element’s visibility property is not hidden
  • The element has a non-zero width and height.

The method does not take the element’s relative z-index value, opacity, or other factors that determine its actual visibility into account.

filterHidden()

Finds hidden elements.

TestCafe considers an element hidden if the element fits at least one of the following criteria:

  • The value of the element’s display property is none
  • The value of the element’s visibility property is hidden
  • The value of the element’s width or height is zero.

Elements can be invisible to the user for reasons other than the ones described above.

filter(cssSelector)

Finds elements that match the specified CSS selector.

For example, filter(‘.someClass’) selects elements with the someClass class.

filter(filterFunction)

Finds elements that meet the conditions of the filterFunction function.

The filterFunction function exposes the following variables when it iterates over the array of page elements:

Parameter Description
node Current DOM node.
idx The current DOM node’s index.
NOTE

The filter function cannot contain:

Related element lookup methods find elements related to the existing element selection.

find

  • find(cssSelector) - Looks for element descendants that match the specified CSS Selector.

  • find(filterFunction) - Filters element descendants with a function.

parent

  • parent() - Returns an array of parent elements, starting with the closest relatives.

  • parent(n) - Returns an array of n-th closest parent nodes. The n parameter is an integer. If n is negative, the method returns an array of n-th most distant parent nodes.

  • parent(cssSelector) - Looks for parent elements that match the CSS Selector parameter.

  • parent(filterFunction) - Filters parent elements with a function.

child

  • child() - Returns an array of element descendants, starting with direct descendants.

  • child(n) - Returns an array of n-th closest descendant nodes. The n parameter is an integer. If n is negative, the method returns an array of n-th most distant descendant nodes.

  • child(cssSelector) - Looks for element descendants that match the CSS Selector parameter.

  • child(filterFunction) - Filters element descendants with a function.

sibling

  • sibling() - Returns an array of sibling elements, starting with the closest relatives.

  • sibling(n) - Returns an array of n-th closest sibling nodes. The n parameter is an integer. If n is negative, the method returns an array of n-th most distant sibling nodes.

  • sibling(cssSelector) - Looks for element siblings that match the CSS Selector parameter.

  • sibling(filterFunction) - Filters element siblings with a function.

nextSibling

  • nextSibling() - Returns an array of succeeding sibling elements, starting with the closest relatives.

  • nextSibling(n) - Returns an array of n-th closest succeeding sibling nodes. The n parameter is an integer. If n is negative, the method returns an array of n-th most distant succeeding sibling nodes.

  • nextSibling(cssSelector) - Looks for elements’ succeeding siblings that match the CSS Selector parameter.

  • nextSibling(filterFunction) - Filters elements’ succeeding siblings with a function.

prevSibling

  • prevSibling() - Returns an array of preceding sibling elements, starting with the closest relatives.

  • prevSibling(n) - Returns an array of n-th closest preceding sibling nodes. The n parameter is an integer. If n is negative, the method returns an array of n-th most distant preceding sibling nodes.

  • prevSibling(cssSelector) - Looks for elements’ preceding siblings that match the CSS Selector parameter.

  • prevSibling(filterFunction) - Filters elements’ preceding siblings with a function.

shadowRoot

  • shadowRoot() - Returns the shadow root node. Chain to other methods to traverse the shadow DOM. Throws an error if the shadow tree is closed or does not exist.
NOTE

You cannot target the shadow root node. Only use the shadowRoot() method to enter the shadow DOM.

For more information about shadow DOM testing, read Test the Shadow DOM.

Filter Elements with a Function

Finds elements that meet the conditions of the filterFunction function.

The filterFunction function exposes the following variables when it iterates over the element array:

Parameter Description
node Current DOM node.
idx Current node’s array index
originNode The origin node.

The following example demonstrates how to use a filter function with the find method:

Filter function

Filter function limitations

Filter functions can not include:

Element Selector Timeout

When TestCafe runs tests, it automatically waits for action targets to appear. The value of the element selector timeout variable defines the maximum waiting time. If a visible DOM element that matches a Selector query does not appear on the page within the element selector timeout, the test fails. Adjust the value of the timeout in the run configuration’s Advanced options panel.

See Automatic Waiting for more information.

Test the Shadow DOM

TestCafe Studio does not record actions that target the Shadow DOM. You cannot access Shadow DOM elements directly from the DOM, either. To interact with the Shadow DOM, identify the root node of a shadow tree with the shadowRoot method. Use other selector methods to traverse the shadow tree.

The example below populates an input field inside a Shadow DOM. The shadowRoot method selects the root node of a shadow tree. The find method locates the desired element inside the shadow DOM.

Accessing the Shadow DOM

TIP

You can save and reuse shadowRoot Selector queries.

WARNING

You cannot perform actions with the shadowRoot() element, or use it in assertions. Use this element as an entry point to the shadow DOM.

Automatic Selectors

Automatic Selector Generation

TestCafe Studio automatically generates Selectors:

  • When you interact with the page during test recording.

    When you record a codeless test, TestCafe Studio adds Selector queries to action settings.

    Element selector

    When you record a test script, TestCafe Studio adds Selector queries to action code.

  • When you use the element picker (codeless tests only).

    Click the Element Picker Pick the target element button next to the Element Selector field in the action parameters area, and select a page element. TestCafe Studio generates Selectors for this element and picks one of them to populate the Element Selector field. For some elements, TestCafe generates a list of Selector candidates.

    Picking an element

  • When you use the Selector Inspector on the Recording Panel Tab (test scripts only).

    TestCafe Studio displays the Recording Panel when you record test scripts. If you open the Selector Inspector tab and click a page element, TestCafe generates a list of Selectors that match your element. Select an entry from the drop-down menu and press ‘Insert’ to insert that Selector string into the script.

    Selector Inspector

Pick a Selector

TestCafe Studio generates more than one Selector query for each action. It ranks them in order of component priority, and automatically enables the top entry.

Sometimes the default Selector query doesn’t work well with user code. This is often the case when an application generates dynamic IDs or class names.

If you aren’t satisfied with the default Selector query, click the button next to the Selector Input field and view the list of Selector candidates. The Selector Input field is located in codeless test actions’ action parameters area, as well as on the test script recording panel. Click an entry from the Selector list to enable a different Selector query.

Selector list

If default Selector queries rarely fit you, and you routinely find yourself picking alternative Selectors, you can help TestCafe Studio generate better Selector queries automatically. Introduce custom Selector keywords and/or change your component priority to get better Selector suggestions.

Element Highlighting

TestCafe Studio highlights page elements to help users pick the correct Selector:

Selector Components

TestCafe Studio constructs auto-generated Selectors from the following components:

Component Category Matching Element Examples Default Priority
tagName An element with the specified HTML tag (<html>, <body>, <header>, <footer>, and <main> tags only) 'body' 1
id An element with the specified ID. 1. matches an element with id="populate" : '#populate'
2. matches an element with an auto-generated ID:
'div' > withAttribute('id', /test1_ctl\d+_test2/)
2
text An element with the specified innerText (or textContent — for option elements) 'p' > withText('Hello world!') 3
class An element of the specified class. [class="container"] 4
attr An element with the specified attribute.
The following attributes can be used: alt, name, title, and data-* (unless you create a custom selector type for the attribute).
1. one attribute: '[name="name"]'
2. multiple attributes: '.some-class[alt="someAlt"]' > withAttribute('data-attr', /foo\s+bar/)
5
dom An element at the specified position in the DOM hierarchy. 'body' > find('form') > find('div') > find('header') > find('h1') 6

Add a Custom Attribute

TestCafe Studio can generate Selectors that reference custom HTML attributes. Read the section about custom attributes to learn why this is desirable.

  1. Open the Selector Generation pane in the Record Configuration Dialog, click Add Custom Attribute, and specify the attribute’s name.
  2. Elevate the priority of the attribute to make sure that TestCafe Studio prioritises it when it generates Selectors.

Adding a custom attribute

Selector Priority

Different categories of Selector keywords have different priority levels. When TestCafe Studio generates Selectors, it favors higher priority keywords.

Open the Selector Generation pane of the Record Configuration Dialog to view the list of Selector components, ranked in order of their priority. Re-order the list to change component priority.

  • Raise the priority of a keyword (like the aforementioned data-test-id custom attribute) to make sure that automatic Selector queries feature it whenever possible.

  • Lower the priority of a keyword if it offers no semantic value (like a dynamic ID), and you want TestCafe Studio to avoid it.

  • Hide a keyword to completely disable a Selector component.

Drag and drop selector types

Compound Selector Priority

The priority of compound Selectors depends on the priority of their individual components.

  • The first component of a Selector determines the Selector’s initial priority.
  • When TestCafe Studio decides between two Selectors with an identical first component, the priority of the second component determines the outcome, and so on.

Compound selector example

Element Selector Creation Dialog

Use the Element Selector Creation Dialog to create custom selectors for codeless tests.

TestCafe Studio displays the Element Selector Creation Dialog when you add a new Define Element Selector action.

The Define Element Selector action

Additionally, you can access the dialog:

Start the query

You can start the Selector query with one of the following components:

NOTE

If you specify a selector, TestCafe Studio highlights all matching elements

Add Selector Methods

Chain one or more element selector methods to filter the array of elements, or search for related elements.

Click the Add Method button and select a method from the list.

Add method

Specify the parameters (if needed) and click Done.

Method parameters

Remove Methods

Click the Remove button next to the method entry in order to remove it.

Remove method

Reorder Methods

Drag method entries to reorder them.

Example

The animation below demonstrates how to create a reusable element selector that:

  1. locates all ul elements;
  2. finds label elements within them;
  3. finds a div.container parent for each label.

Selector Constructor

NOTE
  • Element selectors can return multiple items. If you use this selector in an on-page action, the action is performed on the first matching element. If you use it in an assertion, the assertion checks properties for the first element.

  • If added methods filter out all elements, an element selector returns null. If a test action or an assertion uses this selector, the test fails.

Reuse Element Selectors

Selector queries take time to resolve. Tests that repeat identical Selector queries are slower and harder to maintain. Save the results of a Selector query to only declare it once, but use it multiple times.

Save Selectors (test scripts)

Assign the value of a Selector query to a constant, and use that constant later in code.

const myBeautifulSelector = Selector('div').withText('hello world');
<…>
await t.click(myBeautifulSelector);

Define Element Selector action (codeless tests)

The Define Element Selector action allows you to re-use the results of a Selector query.

  1. Add the Define Element Selector action from the Actions panel.

  2. Specify a unique name for your Selector. Names cannot include the following reserved words: t, fixture, test, Selector, ClientFunction, RequestLogger, RequestMock, RequestHook.

  3. Use the Element Selector Creation Dialog to generate a Selector query.

Action icon

  1. Reference your new Selector when you define actions and assertions.