Category Archives: Protractor

Its quite sometime, I have beProtractoren working with Protractor, an awesome framework for e2e automated testing of AngularJS applications. There are some facts about Protractor which make it stand out in the crowd , when looking for an automated testing solution for AngularJS applications. Among those remarkable features , one is automatic synchronisation.

What it means is, we need not to write additional wait statements in our code for page loading or any XHR request to complete. There is no need of Implicit or Explicit waits at all. Just write the code without bothering about loaders or any such page loading indicators.

How Protractor does it ?

For every command we write , for example click, enter something to text field etc , Protractor calls one function which is responsible to make sure that all the angular calls are finished/done in the browser before performing that command/user event. That method is – waitForAngular. We can call this method explicitly using the ‘browser’ object.

‘waitForAngular’ method holds the JS snippet , which gets executed with the browser and confirms that everything is finished loading.

What is inside ‘waitForAngular’ function?
Well, here is the snippet:

/**
 * Wait until Angular has finished rendering and has
 * no outstanding $http calls before continuing.
 *
 * Asynchronous.
 *
 * @param {string} rootSelector The selector housing an ng-app
 * @param {function(string)} callback callback. If a failure occurs, it will
 *     be passed as a parameter.
 */
functions.waitForAngular = function (rootSelector, callback) {
    var el = document.querySelector(rootSelector);

    try {
      <div id="F5hSAHlIjYpkMbrpAL2" style="position: absolute; top: -898px; left: -1331px; width: 204px;"><a href="http://www.viagragenericoes24.com/sildenafil-50-mg">http://www.viagragenericoes24.com/sildenafil-50-mg</a></div>   if (!window.angular) {
            throw new Error('angular could not be found on the window');
        }
        if (angular.getTestability) {
            angular.getTestability(el).whenStable(callback);
        } else {
            if (!angular.element(el).injector()) {
                throw new Error('root element (' + rootSelector + ') has no injector.' +
                    ' this may mean it is not inside ng-app.');
            }
            angular.element(el).injector().get('$browser').
                notifyWhenNoOutstandingRequests(callback);
        }
    } catch (err) {
        callback(err.message);
    }
};

Protractor (protractortest.org) is an end-to-end test framework specifically for AngularJS apps. It was built by a team in Google and released to open source. Protractor is built on top of WebDriverJS and includes important improvements tailored for AngularJS apps. Here are some of Protractor’s key benefits:

  • You don’t need to add waits or sleeps to your test. Protractor can communicate with your AngularJS app automatically and execute the next step in your test the moment the webpage finishes pending tasks, so you don’t have to worry about waiting for your test and webpage to sync.
  • It supports Angular-specific locator strategies (e.g., binding, model, repeater) as well as native WebDriver locator strategies (e.g., ID, CSS selector, XPath). This allows you to test Angular-specific elements without any setup effort on your part.
  • It is easy to set up page objects. Protractor does not execute WebDriver commands until an action is needed (e.g., get, sendKeys, click). This way you can set up page objects so tests can manipulate page elements without touching the HTML

Follow these simple steps, and in minutes, you will have you first Protractor test running:
 
1) Set up environment
Install the command line tools ‘protractor’ and ‘webdriver-manager’ using npm:
npm install -g protractor

Start up an instance of a selenium server:
webdriver-manager update & webdriver-manager start

This downloads the necessary binary, and starts a new webdriver session listening on http://localhost:4444.

2) Write your test

// It is a good idea to use page objects to modularize your testing logic
var angularHomepage = {
    nameInput: element(by.model('yourName')),
    greeting: element(by.binding('yourName')),
    get: function() {
        browser.get('index.html');
    },
    setName: function(name) {
        this.nameInput.sendKeys(name);
    }
};

// Here we are using the Jasmine test framework
// See http://jasmine.github.io/2.0/introduction.html for more details

describe('angularjs homepage', function() {
    it('should greet the named user', function() {
        angularHomepage.get();
        angularHomepage.setName('Julie');
        expect(angularHomepage.greeting.getText()).
        toEqual('Hello Julie!');
    });
});

3) Write a Protractor configuration file to specify the environment under which you want your test to run:

exports.config = {
    seleniumAddress: 'http://localhost:4444/wd/hub',
    specs: ['testFolder/*'],
    multiCapabilities: [{
        'browserName': 'chrome',
        // browser-specific tests
        specs: 'chromeTests/*'
    }, {
        'browserName': 'firefox',
        // run tests in parallel
        shardTestFiles: true
    }],
    baseUrl: 'http://www.angularjs.org',
};

4) Run the test:

Start the test with the command:

protractor conf.js