Monday, June 17, 2013

Selenium: Dealing with HTML loading modal panel

While playing back a test for a java rich faces application, the test was failing in the middle, debugging and playing back step by step, the test was passing with no issues. Looking more into the steps, there was a step that is causing ajax call, and after it there is a button click step, the one that was failing was the next one after the button click. When I checked the screen, there was a loading panel displayed during the ajax call, freezing all the screen, so I figured out that when this loading panel is displayed, selenium was able to find the button and click on it, but it is not actually clicked on the UI of the application, which cause that next step after to fail.

To resolve this, first I tried to look for something to make sure the button is clickable, I found something but for Java, and doesn’t exist for .NET

wait.until(elementToBeClickable(By.partialLinkText("SomeID")));

My test was on IE, and when I tried it with java, I had problems creating the selenium session with the selenium IE server.

Then I thought of something else, to identify any element change in the page that tells that the ajax call is done, then I can use this before the button click, to make sure it is clickable. I looked into the html page before, during and after the ajax call and compared. Before the call and when the loading panel was not visible, I found  hidden div with ID ajaxLoadingModalPanelContainer, it looked like below

<div id="ajaxLoadingModalPanelContainer" class="rich-modalpanel " style="position: absolute; z-index: 100; background-color: inherit; display: none;">

when the loading panel was visible, there was a div in the body like below (same as above, but the display style is gone)

<div id="ajaxLoadingModalPanelContainer" class="rich-modalpanel " style="position: absolute; z-index: 100; background-color: inherit;">

After the ajax call, the loading panel disappears and it changes back to have “display:none”

<div id="ajaxLoadingModalPanelContainer" class="rich-modalpanel " style="position: absolute; z-index: 100; background-color: inherit; display: none;">

I then created a function to wait for the ajaxLoadingModalPanelContainer div to be displayed, then to wait until it is hidden again like below

public void WaitForModalPanel()
{
string element_xpath = ".//*[@id='ajaxLoadingModalPanelContainer' and not(contains(@style,'display: none'))]";
WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 2, 0));
wait.Until(ExpectedConditions.ElementIsVisible(By.XPath(element_xpath)));
element_xpath = ".//*[@id='ajaxLoadingModalPanelContainer' and contains(@style,'DISPLAY: none')]";
wait.Until(ExpectedConditions.ElementExists(By.XPath(element_xpath)));
}


Calling the above function before the button click, the button click was also clicked on the UI and the test was passing successfully