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,
or \n
) with their unicode counterparts when you use Selector.WithText or Selector.WithExactText to filter the page.
Example
<html>
<body>
<p>Click 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 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.