I have some (Angular JS template) HTML as follows:
<div class="data-handler-container">
<div class="row">
<div class="data-handler" ng-if="dataController.showDistance()">
<p>{{ 'Item Count' | translate}}
<p class="metric">{{dataController.project.item_total | converter:dataController.user.unit | number: 6}}<span class="unit">{{dataController.user.unit}}</span></p>
</div>
<div class="data-handler">
<p>{{ 'Total Time' | translate}}</p>
<p class="metric">{{dataController.project.time_total | format:'time':'hh:mm:ss'}}</p>
</div>
</div>
</div>
I am now writing e2e tests using protractor. I need to identify the metrics elements so I can access the values in my tests.
I don't think I can simply use the class
in this case, as the first element is in an ng-if
so might not be there. I would have to identify by class, and then write some logic in my tests to count the items in the returned array - and match them up depending on the count. In this example, it would not be too complex, but in other cases it would be unwieldy.
I could select the paragraph after the item with a certain value - so Total Time
for example, which would work, but seems less than ideal. What if another page element has the same text - my tests need to be updated again.
I can't identify the items by model as far as I know, as they are passed through filters, and I don't want to specify all filters etc... as part of the selector.
- Is there n ideal way to identify the metrics for testing?
I would go with by.binding locator which acts as a partial match:
var itemTotalElm = element(by.binding('dataController.project.item_total'));
var timeTotalElm = element(by.binding('dataController.project.time_total'));
- If there is no ideal way, what is the best way without manipulating the HTML?
The best way I've found is using Andres chrome extension tool elementor. You'll be amazed how easily the tool helps you identify the best possible locators and even shows you the total page counts matching the current page.
- What is the best way if changing HTML is ok?
I believe that the QA automating the tests should be able and encouraged to update the HTML source code as long as he follows some good practices, e.g. add html class names starting with e2e-
so developers knows the purpose of the selector, e.g.
<p class="metric e2e-item_total">
Then you can target it with
var itemTotalElm = $('.metric.e2e-item_total');
- Is it ok in general to alter HTML to make it easier for tests to identify components?
Answered in 3 plus would add that should only update the underlying HTML as long as there is no good selector available so in this case by.binding
should suffice.
If you're looking to add logic in your tests like "if there are more than 5 total items tests this else test that" that might be an indication of poor control of your scenario tests data. If you can't be deterministic of the state of the current page under test then how are you reliably going to find bugs through end-to-end? I mean, if you are reacting to the current state that means you are not validating it properly beforehand, you may be missing to properly seed your test data and this also helps reproducing bugs later on.