Selector.addCustomDOMProperties Method
Adds custom properties to the Selector object.
Use the addCustomDOMProperties
method to retrieve DOM element properties not included in the standard Selector API.
Selector().addCustomDOMProperties({
property1: fn1,
property2: fn2,
/* ... */
}) → Selector
Parameter | Type | Description |
---|---|---|
property1 , property2 , … |
String | Property name |
fn1 , fn2 , … |
Function | Client-side function that calculates the property value. |
Functions that calculate property values (fn1
, fn2
, …) accept the following parameter:
Parameter | Type | Description |
---|---|---|
node |
Object | The DOM node. |
Example
import { Selector } from 'testcafe';
fixture`Selector.addCustomDOMProperties`
.page`https://devexpress.github.io/testcafe/example/`;
test('Check Label HTML', async t => {
const label = Selector('label').addCustomDOMProperties({
innerHTML: el => el.innerHTML,
});
await t.expect(label.innerHTML).contains('input type="checkbox" name="remote"');
});
If you use TypeScript, extend the Selector interface with your custom properties:
interface CustomSelector extends Selector {
innerHTML: Promise<any>;
}
interface CustomSnapshot extends NodeSnapshot {
innerHTML: string;
}
// via selector property
const label = <CustomSelector>Selector('label').addCustomDOMProperties({
innerHTML: el => el.innerHTML
});
await t.expect(label.innerHTML).contains('input type="checkbox" name="remote"');
// via element snapshot
const labelSnapshot = <CustomSnapshot>await label();
await t.expect(labelSnapshot.innerHTML).contains('input type="checkbox" name="remote"');
Propagation
TestCafe propagates all custom properties and methods down every selector chain.
import { Selector } from 'testcafe';
fixture`Selector.addCustomDOMProperties propagation`
.page`https://devexpress.github.io/testcafe/example/`;
test('Propagate custom properties', async t => {
const div = Selector('div').addCustomDOMProperties({
innerHTML: el => el.innerHTML,
});
await t
.expect(div.innerHTML).contains('<header>')
.expect(div.nth(2).innerHTML).contains('<fieldset>')
.expect(div.withText('Submit').innerHTML).contains('<button');
});
Additions to your Selector chain change the target of your custom method. You may unwittingly request a property that does not exist on the client. Make sure your code does not fail due to propagation:
import { Selector } from 'testcafe';
fixture`Selector.addCustomDOMProperties propagation in the chain`
.page`https://devexpress.github.io/testcafe/example/`;
test('Check Label HTML', async t => {
const fieldSet = Selector('fieldset')
.addCustomDOMProperties({
legend: el => el.querySelector('legend').innerText,
})
.addCustomMethods({
getLabel: (el, idx) => {
return el[0].elements[idx].labels[0];
},
}, {
returnDOMNodes: true,
});
// This assertion passes.
await t.expect(fieldSet.nth(1).legend).eql('Which features are important to you:');
// This line throws an error.
try {
await t.expect(fieldSet.nth(1).getLabel(3).textContent)
.eql('Easy embedding into a Continuous integration system');
}
catch (err) {
await t.expect(err.errMsg).eql('TypeError: Cannot read properties of null (reading \'innerText\')');
}
// When TestCafe evaluates "getLabel(3)", it also tries to propagate
// the "legend" property to the result. So, it queries for a
// <legend> inside the <label> element, which returns nothing.
});