TestComplete and automating dynamic JavaScript menus

TestComplete Online TrainingIf you read my blog regularly you know I conduct TestComplete training where we teach people how to use the product and get the most out of their automation investment. One of the issues that comes up regularly is how to deal with dynamic content on web pages such as popup menus implemented using JavaScript. I’ve blogged before about automation being hard and when it comes to web applications and dynamic display of HTML driven by JavaScript the challenge can be quite steep particularly for someone first learning GUI automation.

Automating Web Applications

GUI automation for web applications can be very different than testing standard Windows applications and there are some tools and techniques that can really help to resolve these particular challenges. Let’s take a look at an example.

Let’s there’s a dynamic JavaScript menu control on your application like this:

 image

The challenge for a recorder with this example can be mouse hover behavior of the menu. Hovering the mouse over the menu items activates the submenus automatically and some recording tools don’t capture that information. TestComplete records selection of the Orders item as follows in JScript:

function Test1()
{
  var  iexplore;
  var  page;
  TestedApps.iexplore.Run(1, true);
  iexplore = Aliases.iexplore;
  page = iexplore.pageHttpTrainingFalafelComDynami;
  page.ToURL("http://training.falafel.com/dynamiccontent/");
  page.formForm1.panelMenu1n3items.table.cell.tableMenu16Menu115.cell.linkOrder.Click();
  //Please wait until download completes: "http://training.falafel.com/dynamiccontent/NewItem.aspx"
  iexplore.pageHttpTrainingFalafelComDynami1.Wait();
}

Playing back this recording results in error indicating that TestComplete was trying to click outside the bounds of an object which in this case happens to be the Orders item but since it never appears on screen it’s impossible to click on it at all. Fortunately, there is an alternative which is to write a function that will handle menu selection for any item within the menu control using a familiar syntax to address the menu items.

However, there’s the minor issue of understanding exactly what it takes to develop such a routine and that means digging into the HTML of the page and coming up with a mechanism to uniquely identify the various menu items. To aid this process I leverage the Internet Explorer Developer Toolbar or the Developer Tools add-in which allows us to dig into the page right from within IE. Let’s take a look:

If you examine the href property of the Customer menu item you can see that it contains a string that’s unique, ‘Add\\New\\Customer’. In fact, the entire menu hierarchy has a similar structure which means our routine could search for items with that attribute, hover the mouse over each subitem and finally click the Orders items. Of course, if you examine the Orders item its href will be an actual URL an not a JavaScript call so we’ll need to find that item using it’s innerText property. Ok, now let’s look at the code, which doesn’t include any error checking:

function AspNetMenuSelect(page, menuitem)
{
  var items = menuitem.split("|");
  var itemstr = "";
  var count = 0;
  while(count < items.length - 1)
  {
    itemstr = itemstr + items[count];
    item = page.NativeWebObject.Find("href", "*" + itemstr + "*", "a");
    itemstr = itemstr + "\\\\";   // Add\\New\\Customer
    item.HoverMouse();
    count++;
  }
  item = page.NativeWebObject.Find("innerText", items[count], "a");
  item.Click();
  page.Wait();
}

The function is called as follows:

AspNetMenuSelect(page, “Add|New|Customer|Order”);

Where “page” represents Sys.Process(“iexplore”).Page(“*”). If you’re not familiar with TestComplete it exposes a “Page” object off of Internet Explorer (and Firefox) allowing a test to access elements of a web page.

The second parameter is a “|” separated string of menu items to select. The code breaks the string up into an array, searches the page looking for an anchor tag that has an href with the specified value and hovers the mouse over it. The process then repeats, building up the href the value we identified above until the last parent menu item is reached. The final piece is to locate the last menu item using the innerText property, click on it then wait for a page load to complete.

If you have a test automation tool, any tool, go ahead and record this test case where you click on the item highlighted above using a non-journaling mode and see how well it plays back. Then, post a comment below and let me know the outcome I’d be really interested in seeing some of the other tools compare. I will note that Selenium had no problem recording this example though it uses an entirely different technique.

Admittedly, it’s not terribly satisfying when you record a test and your tool of choice fails to replay it properly, a situation that can understandably leave people frustrated. It’s important to grasp the limitations of your recording software as I’ve yet to find one that works flawlessly in all cases. However, in the case of TestComplete, through scripting, we can dig in at a lower level and solve problem.

imageNow, if you made it this far which I hope you did because you can watch a video of this whole process on Falafel Software’s new tv.falafel.com.

Ok, so that was a bit of tease… 🙂