//

How to inject JavaScript using Robot Framework and Selenium

25.5.2010 | 4 minutes of reading time

My team has chosen – amongst other TDD approaches – ATDD as the way to go. We are delighted every day by the Robot Framework and the related Selenium Library . We write our tests in a natural language like syntax. For complex web applications, you will sooner or later need to perform assertions for which no standard keywords are available. In this article, I’ll show you how to inject JavaScript into the HTML GUI under test, which enables you to perform complex or unusual assertions

In the case I’m using for this example, we have developed a website on which different insurance products are compared after a couple of calculation steps have been performed. The website is quite smart, thus it is also able to sort the products based on different criteria. Another feature is a filter that allows the customer to – well – filter the products 🙂 If the customer selects one of the filters, certain products will become invisible.

For the tests, this implies that we need to have automated tests for both the sorting and the filter mechanism. I’ll use the filter as an example here. The test case looks roughly like this (I’ve introduced a little abstraction of course):

1*** Keyword ***
2Behaviour
3    [Arguments]  ${Filter}  ${o1}  ${o2}
4 
5    Given that there is a product page for XYZ 
6 
7    If the filter is set to ${Filter}
8 
9    Then product A is optically ${o1}
10    And product B is optically ${o2}
11 
12| *Test Case* | | *Filter*    | *o1*      | *o2*      |
13| 1 | Behaviour | no filter   | visible   | invisible |
14| 2 | Behaviour | F1          | invisible | visible   |
15| 3 | Behaviour | F2          | visible   | invisible |
16

There is no predefined keyword for visibility checks in the Selenium Library. In the Selenium IDE you can use “assertVisible”, but we prefer to use JavaScript. Our templates use Prototype, which provides quite a couple of very comfortable methods. I had the following idea how I might check the visibility of an element:

  1. Add a hidden input to the DOM tree
  2. Set the hidden input’s value to true or false, which indicates visibility of the targeted element
  3. Finally, check that input’s value using “Text Field Value Should Be”.

Okay, so I wrote the following JavaScript function that performs the hidden input magic:

1function prepareHiddenField() {
2  if(!$('HIDDENROBOT')) {
3    Element.insert(
4      $('products'),
5      new Element(
6        'input',
7        {type:'hidden', id:'HIDDENROBOT'}
8      )
9    );
10  }
11 
12  $('HIDDENROBOT').value = $('product_A').visible();
13}
14

In order to inject this function into the page being tested, it has to be transformed into an anonymous function that immediately calls itself. Also, the entire JS code must be put on a single line in order to avoid line break foobar in the BDD file. Kudos to those who can read this – here is the result, spiced up with a variable “pid” as in “product ID”:

1(function(){!$('HIDDENROBOT') && Element.insert($('products'), new Element('input', {type:'hidden', id:'HIDDENROBOT'})); $('HIDDENROBOT').value=$('product_${pid}').visible();})()
2

So – now we can write the required Robot keywords:

1Prepare hidden visibility field for ${product}
2    ${pid} =  productId for  ${product}
3    Call Selenium Api  runScript  theJavaScriptAsShownAbove
4 
5product ${product} is optically visible
6    Prepare hidden visibility field for ${product}
7    Text Field Value Should Be  HIDDENROBOT  true
8 
9product ${product} is optically invisible
10    Prepare hidden visibility field for ${product}
11    Text Field Value Should Be  HIDDENROBOT  false
12

This example may seem to lack elegance, but I hope you see the point I’m trying to make. In many cases, CSS or XPath selectors won’t help you much, for example if you intend to check style attributes set by visual effects. To do such things, JavaScript injection is a very handy tool.

I mentioned earlier that we test the re-sorting of the compared products as well, so I’ll give you another example which is a little more complex. Upon sorting, the order of elements inside the DOM tree is changed. Thus, we need to assert that those DOM tree elements have the correct order after they have been sorted.

To do this, we require n hidden inputs, matching n products being compared. Here’s an excerpt from the test case, using hard-coded values:

1Then product B is in position ${posB}
2And product A is in position ${posA}
3

So, let’s create a hidden input for each product:

1(function(){
2  Element.insert(
3    $('products'),
4    new Element(
5      'input',
6      {type:'hidden', id:'HIDDENROBOT${index}', value:$$('div.product')[${index}-1].id}
7    )
8  );
9})()
10

The required position is passed as the variable “index”, 1-based, so that we need to reduce it by one in order to get a correct index for the element array collected by $$(‘div.product’).

Here goes the JavaScript in one line again:

1(function(){ Element.insert($('products'), new Element('input', {type:'hidden', id:'HIDDENROBOT${index}', value:$$('div.product')[${index}-1].id})); })()
2

And the entire keyword for the position check:

1product ${product} is in position ${index}
2    ${pid} =  productId for  ${product}
3 
4    Call Selenium API  runScript  theJavaScriptAsShownAbove
5    Text Field Value Should Be  HIDDENROBOT${index}  product_${pid}
6

In this case, we did really not have any chance to use the default Selenium or Robot toolbox. As you can see, injecting JavaScript is a great tool in order to build very complex tests.

Kindly let me advise you that we are offering an ATDD training with Elisabeth Hendrickson on June 21/22 2010. There are still seats available – come join us! 😉

share post

Likes

0

//

More articles in this subject area\n

Discover exciting further topics and let the codecentric world inspire you.

//

Gemeinsam bessere Projekte umsetzen

Wir helfen Deinem Unternehmen

Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.

Hilf uns, noch besser zu werden.

Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.