Tuesday, October 24Be an Automation Engineer

How to evaluate an angular expression using protractor?

Protractor is designed for interacting with a web page like a real user. It is specifically designed for automating AngularJS web applications. So, protractor should have some advantages over other automation tools when it comes to automating AngularJs web applications. I am going to show you one of such advantages that protractor posses.
Note: Here i am not going to discuss about details of AngularJS or its features. Please go through AngularJS documentation if you are new to angular.

Protractor can access variable/object values with the scope of AngularJS:

Protractor can access the elements of a web page like other automation tools. Apart from that, it can evaluate the expressions with in the element’s scope of AngularJS. Protractor has this inbuilt ability. If we want to achieve this with other automation tools like selenium, we need to write some JavaScript code or need to use some third-party tools.

Why do we need to evaluate AngularJS expressions?

Most of the AngularJS web applications contains AngularJS variables and expressions in the DOM elements. AngularJS will handle those expressions and based on the result it will load/hide/delete/update DOM elements.

Let us assume that the DOM element is like below.

<div id='testId1' ng-show='!loading'>
....
<div>

Sometimes we my need to wait for an attribute value and then continue the test further. Generally in protractor, if you want to fetch the value of ng-show, we would use element(byLocator).getAttribute('attributeName'). But here, getAttribute returns $../..> !loading instead of actual evaluated value. So, we need to evaluate the angular stuff and get the final value.

Let us see how we can evaluate an AngularJS expressions

Protractor has evaluate method which we can call on multiple elements or on a single element.

element.all(locator).evaluate(angularExpression); //Returns 'ElementArrayFinder' which then resolves to array of evaluated expression values of each matching element. 
                                    Or 
element(locator).evaluate(angularExpression); //Returns 'ElementFinder' which then will be resolved to actual value of the angular expression. 

 

How the protractor can handle return value types?
  1. primitives – primitives shall be returned as they are.
  2. functions – functions shall be returned as strings.
  3. elements – elements shall be returned as WebElements.

Let us see an example program for evaluating angular expressions for multiple elements.

describe('Evaluate Demo', function () {
    it('Evaluate ng-bind for multiple elements', function () {
        browser.get('http://www.weather.com');
        element.all(by.css('*[data-ng-bind]')).then(function (eles) {
            eles.forEach(function (element) {
                element.getAttribute('data-ng-bind').then(function (attrValue) {
                    element.evaluate(attrValue).then(function (res) {
                        console.log(res);
                    });
                });
            });
        });
    });
});

In the above code we are fetching binding values of all the elements in the page and printing them.

Now, let us see an example program for evaluating angular expressions for single element.

describe('Evaluate Demo', function () {
    it('Evaluate ng-bind for single element', function () {
        browser.get('http://www.weather.com');
        var localeElement = element(by.css('span.locale-lang'));
        localeElement.getAttribute('data-ng-bind').then(function (attrValue) {
            localeElement.evaluate(attrValue).then(function (res) {
                console.log(res);
            });
        });
    });
});

In the above program, we are evaluating locale and printing to console log. 

Your typical config file would look like below:

exports.config = {
    capabilities: {
        'directConnect': true,
        'browserName': 'chrome'
    },
    framework: 'jasmine',
    specs: ['./specs/**/evaluateAngularExpression.js'],
    jasmineNodeOpts: {
        defaultTimeoutInterval: 90000
    },
    jasmineNodeOpts: {
        defaultTimeoutInterval: 30000
    }
};
Run the code:
protractor config.js

We can also evaluate the angular expressions using javascript. I will create a separate article to explain that. 

Happy Testing!!!

%d bloggers like this: