ElementFinder.getText()
retrieves the text content of an element by calling innerHTML
and then removing any leading and trailing whitespaces. However, innerHTML
includes all child elements within the element at any level of nesting. While there isn't a built-in property in the DOM to specifically retrieve only first-level text, it can be implemented manually. Text within the DOM is treated as a node and stored in the DOM tree similarly to tag elements, just with different characteristics. By accessing the property Element.childNodes
, we can obtain the first-level children elements of the main element, iterate through them to extract only text nodes, concatenate their content, and return the result.
To streamline this process in Protractor, I have created a custom method that extends the prototype of ElementFinder
. This enhancement allows for simple usage across all Protractor elements. You may choose where to include this additional code, but I recommend placing it before your tests, perhaps in protractor.conf.js.
protractor.ElementFinder.prototype.getTextContent = function () {
// Inject script onto the page
return this.ptor_.executeScript(function () {
// Note: this scope is not specific to Protractor
// Current element
var el = arguments[0];
var text = '';
for (var i = 0, l = el.childNodes.length; i < l; i++) {
// Extract text from text nodes exclusively
if (el.childNodes[i].nodeType === Node.TEXT_NODE) {
text += el.childNodes[i].nodeValue;
}
}
// Optionally trim leading and trailing whitespace
text = text.trim();
return text; // The final outcome - Promise resolves with this value
}, this.getWebElement()); // Pass the current element to the script
};
This method returns a Promise that resolves with the value stored in the text
variable. To apply it:
var el = $('.desc');
expect(el.getTextContent()).toContain('Print this');
// or
el.getTextContent().then(function (textContent) {
console.log(textContent); // 'Print this'
});