Friday, 3 June 2016

A selenium guy hacks to learn Protractor


1. Protractor global variables:

a. browser: Eg. browser.get()
b. element : Eg. element(by.model('yourName'))
c. by : Eg. element(by.model('yourName'))
d. protractor: Eg. protractor.Key

2.element() vs element.all()

Single element:
element( by.binding('appName') );

Collection of elements:
element.all( by.css('[ng-click="openPage()"]') ).get(2).click();


3. by.binding:

In your application:
<span ng-bind="myModel"></span>
<!-- or -->
<span>{{myModel}}</span>

In your test:
element( by.binding('myModel') );

4. by.model:

In your application:
<input ng-model="myModel" />

In your test:
element( by.model('myModel') );


5. by.repeater:

a. In your application
<ul>
  <li ng-repeat="user in users">
      <span>{{user.name}}</span>
  </li>
</ul>

b. In your test
element( by.repeater('user in users').row(0).column('name') );

6. by.css:

a. In your application
<button ng-click="sendMail()">Send mail!</button

b. In your test
element( by.css('[ng-click="sendMail()"]') );

7.Few  more
a. by.select()
b. by.partialButtonText()
c. elementArrayFinder.each()

Full list of available methods
http://www.protractortest.org/#/api

8.Promises based

All Protractor methods are "asynchronous" and return promises.

// Example of getText() promise
element( by.model('zipcode') ).getText()
  .then(function(val) {
    var num = val.substring(0, 4);
    var isNum = !isNaN(num);
    expect( isNum ).toBeTruthy();
  });

9. Simple Page objects

var AngularHomepage = function() {
  this.nameInput = element(by.model('yourName'));
  this.greeting = element(by.binding('yourName'));

  this.get = function() {
    browser.get('http://www.angularjs.org');
  };

  this.setName = function(name) {
    this.nameInput.sendKeys(name);
  };
};

10.Node.JS exports and require

a. Your Page Object file
var AngularHomepage = function() {
  this.nameInput = element(by.model('yourName'));
  this.greeting = element(by.binding('yourName'));
  // ...
};
module.exports = AngularHomepage;

b. Your Test file
var AngularHomepage = require('./homepage.po.js');
describe('HomePage Tests', function() {
   var angularHomepage = new AngularHomepage();
   angularHomepage.nameInput.sendKeys('Rafael');
   //...
});

11.Separate your tests in various test suites

exports.config = {
  seleniumAddress: 'http://localhost:4444/wd/hub',
  capabilities: { 'browserName': 'chrome' },

  suites: {
    homepage: 'tests/e2e/homepage/**/*Spec.js',
    search: ['tests/e2e/contact_search/**/*Spec.js']
  },

  jasmineNodeOpts: { showColors: true }
};

Running specific suite of tests
protractor protractor.conf.js --suite homepage

12.Enable multiCapabilities

exports.config = {
  seleniumAddress: 'http://localhost:4444/wd/hub',

  multiCapabilities: [
{
 'browserName' : 'chrome'
},
{
 'browserName' : 'firefox'
}
  ],

  specs: ['example-spec.js'],

  jasmineNodeOpts: {
    showColors: true
  }
};


13.Using onPrepare

a. Set window size before starting the tests

exports.config = {
  seleniumAddress: 'http://localhost:4444/wd/hub',

  capabilities: {
    'browserName': 'chrome'
  },

  onPrepare: function() {
     browser.driver.manage().window().setSize(1600, 800);
  },

  jasmineNodeOpts: {
    showColors: true
  }
};

b.Export xml results of your Automated Suites

First, install jasmine-reporters:

>>npm install jasmine-reporters
And to keep xml results in Timestamp directories, install mkdirp package:

>>npm install mkdirp

c.//config.js
exports.config = {
  onPrepare: function() {
    var folderName = (new Date()).toString().split(' ').splice(1, 4).join(' ');
    var mkdirp = require('mkdirp');
    var newFolder = "./reports/" + folderName;
    require('jasmine-reporters');

    mkdirp(newFolder, function(err) {
      if (err) {
        console.error(err);
      } else {
        jasmine.getEnv().addReporter(new jasmine.JUnitXmlReporter(newFolder, true, true));
      }
    });
  },
};

14.Using params

Your config.js

exports.config = {
  seleniumAddress: 'http://localhost:4444/wd/hub',

  capabilities: { 'browserName': 'chrome' },

  // This can be changed via the command line as:
  // --params.login.user 'ngrocks'
  params: {
    login: {
      user: 'protractor-br',
      password: '#ng123#'
    }
  },

  jasmineNodeOpts: { showColors: true }
};

Your test:

describe('login page', function() {

  var params = browser.params;

  it('should login successfully', function() {
    element( by.model('username') ).sendKeys( params.login.user );
    element( by.model('password') ).sendKeys( params.login.password );
    element( by.css('[ng-click="login()"]') ).click();
    expect( element(by.binding('username') ).getText() ).toEqual( params.login.user );
  });

});

15.Using jasmineNodeOpts

exports.config = {
  seleniumAddress: 'http://localhost:4444/wd/hub',

  capabilities: { 'browserName': 'chrome' },

  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 30000,
    isVerbose: true,
    includeStackTrace: true
  }
};

16.Protractor waits for Angular to finish its work

Though you can tell it not to be that smart about your non-Angular app:

beforeEach(function() {
   return browser.ignoreSynchronization = true;
});

works for Non anguler based apps too

In your config.js

onPrepare: function() {
   global.isAngularSite = function(flag) {
      browser.ignoreSynchronization = !flag;
   };
}
In your test

beforeEach(function() {
   isAngularSite(false); // isAngularSite(true), if it's an Angular app!
});



No comments:

Post a Comment