Automated UI Tests for an AngularJS Material select item with protractor

Testing AngularJS applications using protractor is quiet cool. It automates the UI testing and ensures consistent quality throughout your project. Experimenting with the new Angular Material I ran into a problem: interacting with select items using the protractor API.

The problem

There are a few ways you can select an option using protractor. A very elegant solution was proposed on stackoverflow. While this works for regular angularjs projects, angular material is a little different. That is because the <option> Tags aren’t actually inserted into the DOM until you click the <select>. That’s why you cannot go straight for the option tag but you need to click the select first But then they aren’t a child of the select tag but rather they are inserted at the bottom of the page with an overlay over the rest of the page.

md-option-browser-developer

If you try the mentioned solution above using a

element(by.cssContainingText('option', '10')).click();

you’ll get a

NoSuchElementError: No element found using locator: by.cssContainingText("option", "10")

There are actually no option (or md-option) tags on the page until you click the select tag. Okay so select.click() first then option.click(), but if you select the option tag right away and proceed to the next select tag an odd error occurs

element.all(by.css('md-select')).each(function (eachElement, index) {
    eachElement.click();                    //select the <select> 
    element(by.css('md-option')).click();   //select the first md-option
    });
unknown error: Element is not clickable at point (253, 520). Other element would receive the click: <md-backdrop class="md-select-backdrop md-default-theme"></md-backdrop>

This is because of the overlay that Angular Material puts on the display. It doesn’t disappear right away. So we need to wait for the material effects to take place.

the solution (quickfix):

element.all(by.css('md-select')).each(function (eachElement, index) {
    eachElement.click();                    //select the select
    browser.driver.sleep(500);              //wait for the renderings to take effect
    element(by.css('md-option')).click();   //select the first md-option
    browser.driver.sleep(500);              //wait for the renderings to take effect
});

now the selection works one at a time and angular material has enough time to take away that overlay <md-backdrop> which is in the way of clicking our second <select> tag. However this isn’t the most elegant solution. Maybe in future protractor versions, the server waits for angularjs to finish its DOM changes or something.

Overall though, both the material design implementation of angularjs as well as TDD using protractor and jasmine / karma work very well.

5 thoughts on “Automated UI Tests for an AngularJS Material select item with protractor”

  1. Few Corrections..

    element.all(by.css(‚md-select‘)).each(function(eachElement) {
    eachElement.click(); //select the select
    browser.driver.sleep(500); //wait for the renderings to take effect
    element(by.css(‚md-option‘)).click //select the first md-option
    browser.driver.sleep(500); //wait for the renderings to take effect
    });

  2. You’re codeblock is incomplete, yet this is the first hit on google with my searches, so I figured I’d post a comment with the code. Also, better to use waitForAngular() than sleep.

    element.all(by.css(‚md-select‘)).each(function (eachElement, index) {
    eachElement.click(); // select the
    browser.waitForAngular(); // wait for the renderings to take effect
    element(by.css(‚md-option‘)).click(); // select the first md-option
    browser.waitForAngular(); // wait for the renderings to take effect
    });

    1. Hey. thx for the waitForAngular fix. Other than that, I dont see any real differences though.. did you mean something else that is „incomplete“?

  3. Hey, do you know how I can test this using a unit test?

    var dropDown = element.find(‚md-select‘);
    dropDown.triggerHandler(‚click‘);
    scope.$digest();
    console.log(element); //compiled hmtl

Kommentar verfassen

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.

%d Bloggern gefällt das: