I am currently in process of creating a framework using Protractor. I was trying to use cssContainingText locator given by the Protractor API. However, the locator failed giving an invalidElement exception, which seemed wierd to me.
The HTML of the page looks like this
<tbody>
<tr class="row2">
<td class="action-checkbox">...</td>
<th class="field-name">
<a href="some_link">someText</a>
</th>
<td class="field-slug">sometext</td>
</tr>
<tr class="row3">
<td class="action-checkbox">...</td>
<th class="field-name">
<a href="some_link">someOtherText</a>
</th>
<td class="field-slug">someothertext</td>
</tr>
<tr class="row4">...</tr>
<td class="action-checkbox">...</td>
<th class="field-name">
<a href="some_link">someThirdText</a>
</th>
<td class="field-slug">somethirdtext</td>
</tr>
I was trying to use the text someText using the following locator-
element(by.cssContainingText('.field-name','someText'));, which weirdly gives an InvalidLocator exception. When I use the following locator element(by.cssContainingText('a','someText')), the code works perfectly fine.
As per what I understand from the explanation given here, and the Protractor implementation given here, the cssContainingText first locates all the elements using the CSS Selector and then matches the required text.
So, it seems perfectly fine to me to use the .field-name class name for the CSS Selector and then match the desired string. However, this fails, which I am not able to understand. Inputs on this would be helpful.
You can view and follow the code in GitHub, starting from the API documentation of cssContainingText.
It comes down to this way of search for content in clientsidescripts.js:
var elementText = element.textContent || element.innerText || '';
if (elementText.indexOf(searchText) > -1) {
matches.push(element);
}
As indexOf() requires an exact match and your th element has neither innerText nor textContent (your <a> tag has), you don't get a result by using the th element.
As for differences between textContent and innerText let me refer to this answer in SO and to this one as well.
For your case:
[textContent]
someText
[/textContent]
[innerText]someText[/innerText]
var properties = ['innerHTML', 'innerText', 'textContent', 'value'];
// Writes to textarea#output and console
function log(obj) {
console.log(obj);
var currValue = document.getElementById('output').value;
document.getElementById('output').value = (currValue ? currValue + '\n' : '') + obj;
}
// Logs property as [propName]value[/propertyName]
function logProperty(obj, property) {
var value = obj[property];
log('[' + property + ']' + value + '[/' + property + ']');
}
// Main
log('=============== ' + properties.join(' ') + ' ===============');
for (var i = 0; i < properties.length; i++) {
logProperty(document.getElementById('test'), properties[i]);
}
<div id="test">
Warning: This element contains <code>code</code> and <strong>strong language</strong> and <a href="www.google.com">a Google link</a>.
</div>
<textarea id="output" rows="12" cols="80" style="font-family: monospace;"></textarea>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With