Selenium and JavaScript-Ajax

What is JavaScript?

JavaScript is a dynamic computer programming language. It is most commonly used as part of web browsers, whose implementations allow client-side scripts to interact with the user, control the browser, communicate asynchronously, and alter the document content that is displayed. It is also used in server-side network programming with frameworks such as Node.js, game development and the creation of desktop and mobile applications.

In good olden days, javascript was mostly aimed at client side validation, however these days with the advent of NodeJs, javascript is a full stack in itself. We can design complete websites with NodeJs+Javascript. There are lots of javascript libraries, but the popular ones used before NodeJs came into existence were jQuery, protoptye, Dojo, YUI and so on. AngularJs is an extremely popular javascript library used these days too.

Relevance to Automation:

While we discussed on the topic Waits and Synchronization, we learnt that when a website loads in a browser, it gets various resources and one of them is javascript resources. When we perform operations on elements, we can tie javascript functions to the events happening on HTML elements.

For example, we can execute a javascript function that has a block of code when I click on a button. The below example shows that a javascript function newAlert() should be called when a click operation is performed on the button.

javascript_alert

 

So, we can call javascript functions (eg. onclick) on various events that happen on the webpage or web elements. There is a whole world of javascript and as we mentioned before it is a full stack these days and hence we are not going to discuss the extreme details here. We are going to focus on what is relevant to Automation. I would recommend to read this javascript tutorial if you are intrigued on the details

So coming back to our discussion, the importance of javascript libraries is around ajax calls. What is ajax ?

Ajax is:

  • AJAX (short for asynchronous JavaScript + XML) is a group of interrelated Web development techniques used on the client-side to create asynchronous Web applications
  • AJAX is about updating parts of a web page, without reloading the whole page.

Without reloading the whole page indirectly means without loading the entire DOM. Remember we talked about how we need to think about HTML DOM when thinking about Selenium Automation. We discussed this extensively in Basic Tutorial here.

This matters to us a lot because Selenium moves forward with the next line of operation as soon as it finds that the DOM loaded. However, if only partial DOM gets updated, how will Selenium know about it [in javascript world, this is called callback]. In other words, we have to create callback functions in our Selenium script that will ensure that the next sequence of operations execute only after ajax calls are completed, that way we can ensure that a certain element is in the state what we expect it to be to receive the operation we perform on it.

If we write Selenium scripts without handling ajax callbacks (on ajax websites), most of them fail intermittently and we have a whole bunch of flaky scripts. And how many of us might have scratched heads on this. In fact almost everyone who has gone through Selenium basics and moving towards next level will encounter this ajax issues.

The ajax calls are implemented in lot of javascript libraries and in this section we will cover how to implement callbacks for the following javascript libraries.

  1. jQuery
  2. Prototype
  3. YUI
  4. Angular Js

How do I identify the javascript library on the website?

The easiest way is to view page source on your webpage as soon as it loaded and search for “script” tags containing the keywords “jquery”,”angular”,”prototpye” etc. It is NOT necessary that if jQuery library is used, the ajax is implemented with jQuery, however chances are very high that it has been. You can always reach the UI developer and ask what js library is used for ajax calls too 🙂

We will cover a more detail section of general Javascript functions using Document and Window object in another section, however most of us would feel the pain with javascript-ajax and hence I am writing this post first.

Agenda:

  • Simple Javascript code execution through browser
  • Window and Document objects
  • Callbacks for jQuery, Prototype, YUI and Angular 
  • Inject JS library script tag
  • Focus on important lines of code
  • Cucumber Scenario and Step Definitions
  • Output
  • Closing Thoughts

1) Javascript execution

Print Document body

Document title (Remember we did the same using @browser.title)

Window location path name

2)jQuery

Whenever jQuery makes ajax call(s), the following counts the number of pending Requests. We want to wait until pending requests will become zero, that way we know we can move forward since the call gets completed. In other words, we will be implementing the jQuery callback in our code

3)Prototype

Whenever prototype makes ajax call(s), the following counts the number of pending Requests. We want to wait until pending requests will become zero, that way we know we can move forward since the call gets completed. In other words, we will be implementing the prototpye callback in our code

4)YUI (Yahoo UI)

Whenever YUI makes ajax call(s), the following counts the number of pending Requests. We want to wait until pending requests will become zero, that way we know we can move forward since the call gets completed. In other words, we will be implementing the YUI callback in our code

5)Angular

Whenever Angular makes ajax call(s), the following counts the number of pending Requests. We want to wait until pending requests will become zero, that way we know we can move forward since the call gets completed. In other words, we will be implementing the Angular callback in our code

6)Injecting a Javascript library script tag

There might be very rare instances where you might have to inject JS libraries into the DOM. This is unlikely because as part of Test Automation, we are supposed to use the resources that the server pushes to the client side, so injecting a js library and raising defects on a website with that invalidates the principles of verification and validation. That said, we might want to inject js library so as to use the rich functions that some libraries provide. For example, maybe selenium is not able to fire an event and a javascript library can do it with a function. 

Please download the folder and extract the files “jQuerify.js” and “prototype.js”. Place them in /features/support/ajax_resources folder

Cucumber Feature:

Step Definitions:

Output:

  • First 3 scenarios are simple javascript execution on window and document objects (We will cover this in detail in JavaScript execution page)
  • “Load javascript framework” scenario demonstrates how we can inject javascript into DOM and use its rich set of functions
  • The rest of the scenarios go into details on how we can handle the ajax calls using jQuery, YUI,Prototype and Angular
  • Unfortunately we would have to delve into the step definition code and understand it. It doesn’t have any specific output to print.

Known Issues:

  • We have sleep statements (sleep 5 after loading jquery library AND sleep 0.5 in Watir::wait). This was required at the point of writing this page, because the script_timeout was NOT working as expected. So we had to give a few seconds for the javascript to execute.