Monday, 6 June 2016

WHAT IS KARMA?

Karma is a JavaScript test runner that works by launching different browsers and running tests against each of them. It records the status of each test so you know which tests failed in certain browsers, making cross-browser compatibility testing incredibly easy. Note that you will need to use Karma with Windows to test in Internet Explorer.

STEP 1: INSTALLATION

Install Karma and the necessary plugins using NPM.
# Install Karma using Node
npm install karma --save-dev
You also need to install a few required plugins before you can start using Karma. First download the correct plugin for your chosen testing framework (Jasmine, Mocha, etc.).
# Install Karma plugin for your chosen testing framework
npm install karma-jasmine --save-dev
Also install the launcher plugins for the browsers you want to execute your tests against. There are launcher plugins for all major browsers.
# Install Karma browser launcher plugins
npm install karma-chrome-launcher --save-dev
npm install karma-ie-launcher --save-dev
*Note: The --save-dev option saves the package as a dev dependency to the package.json file

Is Protractor is better than selenium?

If you ever tested your application using something like Selenium you know that can be very difficult to test your web application that way because the asynchronous nature of the Web, that can change their HTML DOM. 
Angular E2E testing try to reduce some of these problems.
Here, we come with Protractor.
This post tries to help set up the Protractor testing tool in WebStorm IDE.
Protractor is an end-to-end test framework for AngularJS applications. Protractor runs tests against your application running in a real browser, interacting with it as a user would.
The WebStorm IDE is a powerful tool for complex client-side development and server-side development with Node.js.
The testability is a really really cool piece of functionality that Angular provides. It was develpoed around the idea that testing is so important that it should be built into the framework.
To create your Integration testing  you need to use the advantages of the internals in Angular to make lot easier the integration testing in your AngularJS application.


What is Gulp?

Gulp is a javascript task runner that lets you automate tasks such as…
  • Bundling and minifying libraries and stylesheets.
  • Refreshing your browser when you save a file.
  • Quickly running unit tests
  • Running code analysis
  • Less/Sass to CSS compilation
  • Copying modified files to an output directory
form more info. http://brandonclapp.com/what-is-gulp-js-and-why-use-it/

These features will be useful for running protractor project.

Friday, 3 June 2016

Node Require and Exports

A module encapsulates related code into a single unit of code. When creating a module, this can be interpreted as moving all related functions into a file.

---misc.js------
var x = 5;
var addX = function(value) {
  return value + x;
};

Now, before we look at how to expose things out of a module, let's look at loading a module. This is where require comes in. require is used to load a module, which is why its return value is typically assigned to a variable:

var misc = require('./misc');

as long as our module doesn't expose anything, the above isn't very useful. To expose things we use module.exports and export everything we want:

---misc.js------
var x = 5;
var addX = function(value) {
  return value + x;
};
module.exports.x = x;
module.exports.addX = addX;

--usage--
var misc = require('./misc');
console.log("Adding %d to 10 gives us %d", misc.x, misc.addX(10));


There's another way to expose things in a module:

var User = function(name, email) {
  this.name = name;
  this.email = email;
};
module.exports = User;

the last thing to consider is what happens when you directly export a function:

var powerLevel = function(level) {
  return level > 9000 ? "it's over 9000!!!" : level;
};
module.exports = powerLevel;
When you require the above file, the returned value is the actual function. This means that you can do:

require('./powerlevel')(9050);
Which is really just a condensed version of:

var powerLevel = require('./powerlevel')
powerLevel(9050);
Hope that helps!

Setting Up WebStorm for Debugging

To set up WebStorm for Protractor, do the following:
  1. Open the Run/Debug Configurations dialog
  2. Add new Node.js configuration.
  3. On the Configuration tab set:
    • Node Interpreter: path to node executable
    • Working directory: your project base path
    • JavaScript file: path to Protractor cli.js file (e.g. node_modules\protractor\lib\cli.js)
    • Application parameters: path to your Protractor configuration file (e.g. protractorConfig.js)
  4. Click OK, place some breakpoints, and start debugging.

Can we use Protractor in a non-AngularJS app?


Yes, you can!

just add below code in your script file.


browser.ignoreSynchronization = true;

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!
});



Hello World of Protractor


-----------SpecOne.js-------------------------

describe('angularjs homepage', function() {   it('should have a title', function() {     browser.get('http://angularjs.org/');     expect(browser.getTitle()).toContain('AngularJS');   }); });


------------Config.js--------------------------
exports.config = { //The address of a running selenium server.   seleniumAddress: 'http://localhost:4444/wd/hub', //Here we specify the name of the specs files.   specs: ['SpecOne.js'] }



For Running:

1. Start selenium Server

2. Run>protractor conf.js


Thats all.