Machtyn Machtyn - 2 months ago 26
AngularJS Question

testing material design elements in protractor

Is there an easier way to test angular2 pages that utilize material design elements within protractor?

It appears utilizing MD elements within angular2 simplifies a lot of effort. But I'm finding trying to select the various subelements tedious.

That is, take the following example:

<div>
<md-icon class="material-icons step" ng-class="md-24" ng-style="{color: font.color}">
email
</md-icon>
" &nbsp Email Notification
"
</div>


First of all, if I were to try and verify the text, I would have to use a contains method an not an equals method, because the result of a getText on this would be:
"email Email Notification"
.

So my questions are:


  1. Are my developers just not setting id's, or other unique identifier, on the elements properly

  2. Or is there a better way, in Protractor, to test material design element blocks?

  3. Or am I doing something inherently wrong.


Answer

Unfortunately, there is nothing specific for material design in Protractor.

What you can do in cases like these is to get the text of the element, get the text of material design element and replace it:

var div = element(by.xpath("//div[contains(md-icon, 'email')]"));
var icon = div.element(by.tagName("md-icon"));

var text = div.getText().then(function (parentText) {
    return icon.getText().then(function (iconText) {
        return parentText.replace(iconText, "").trim();
    }); 
});

expect(text).toEqual("Email Notification");

This is not pretty at all, but you can generalize it and extract into a helper function, or make a custom jasmine matcher to encapsulate the logic of cleaning up the text of md-icon texts.


Are my developers just not setting id's, or other unique identifier, on the elements properly

Having meaningful IDs or data-oriented classes defining elements though would always help. See how I had to locate the div element with an XPath checking the presence of md-icon element inside.

Imagine something like this instead - much more convenient to deal with:

<div id="email">
  <md-icon id="emailIcon" class="material-icons step" ng-class="md-24" ng-style="{color: font.color}">
      email
  </md-icon>
  <span id="emailLabel">Email Notification</span>
</div>