Selenium 2 has adopted minimalist approach in terms of API. It is a good thing for us the developers that we only need to remember a few things. At the same time, it can be a bad thing if it restricts you from doing what you want. Using Selenium, most of the common tasks involved in UI testing can be easily done using simple API. In this article, I am going to record the workarounds I used for the current UI testing project I am working on.
The first issue is not strictly related to Selenium. There are data collection pages in the website which warn the user that the page is dirty on body unload event using confirm dialog. I have implemented some scenarios in which I was checking how the form reacts to erroneous user inputs. When I close the browser at the end of the scenario, the warning is displayed because the form is dirty. The browser does not close down because it is waiting for confirm dialog. As the confirm dialog is trigger by webDriver.Quit() call, I have lost control of the browser at that point and I cannot interact with confirm dialog anymore.
My workaround is to visit home page at the end of the scenario and if the current form is dirty, the confirm dialog box will appear. Since I am using SpecFlow, I implemented that procedure in [ScenairoTearDown] method. However, I could not assume the dialog would always appear in all scenarios and I had to warp driver.SwitchTo().Alert() call in try catch block. After the home page is loaded, I can call webDriver.Quit() knowing nothing is going to popup and stop the browser from closing down.
Secondly, in Selenium 2 there is only type (SendKeys) function, no paste function. There are some scenarios in which paste is more desirable. For example, you might want to simulate the user pasting some text into the text box. Or you might want to reduce the number of AJAX calls triggered by each keystroke which do not contribute to your test case. I found the following answer in stackoverflow and it served me well.
private void SetValue(IWebElement element, String value)
{
((IJavaScriptExecutor)driver)
.ExecuteScript(
“arguments[0].value = arguments[1]”,
element, value);
}
The next issue was about stale elements. WebDriverWait class does not handles StaleElementException well. For example, I wanted to wait for certain text to appear in the table cells rendered by AJAX callback as below:
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until<IWebElement>(d => d
.FindElements(By.CssSelector(“table .ajaxResult tbody tr”))
.FirstOrDefault(tr => tr
.FindElements(By.TagName(“td”))
.Any(td => td.Text.Contains(“some text”))));
Sometimes, I would get StaleElementException thrown from Until function. It seems the table row collection become stale as more rows get rendered. As suggested by many people in forums, I tried out extending WebDriverWait class and wrapping Until method in try catch block which simply calls itself if StaleElementException is caught.
The other problem which I struggle with is Selenium does not do well when the element of interest is partially hidden. There is a form which is slightly longer than the screen height. As I am filling in the form using SendKeys method the screen would scroll down bit by bit. At some point, I need to click the link at the top of the page which is now partially out of viewport. When I call Click() on that element, nothing happens. If the link is completely out of viewport, Selenium would bring that into viewport and then click it. It seems auto scroll function and click function has different way of calculating if something is in viewport.
Using the Selenium IDE and Export test case as -> C# (WebDriver) function, I could see that the generated code call Click() twice consecutively when the link is completely out of viewport. However, it still does not help with partially out of viewport scenario. MoveToElement and MoveByOffset methods in Actions class only move the mouse pointer but they do not actually scroll the page into position. The only thing I could do to resolve this is to call SendKeys(string.Empty) before calling Click(). On the link elements, SendKeys does not have any effect other than bring them into viewport completely. Once they are in viewport, Click function would happily click them.
After all these, I thought if FireFox driver would do things differently and decided to try out running the website in FireFox. The website uses windows authentication and runs in ASP.NET development server. I had to add the base address as trusted uri in FireFox profile so that it would not prompt for user credentials on first visit. I also noticed UI tests were running way slower than in IE. After a little bit of searching the internet, I found the article which suggested turning off IPv6 in FireFox profile which worked a treat.
FirefoxProfile profile = new FirefoxProfile();
profile.SetPreference(
“network.automatic-ntlm-auth.trusted-uris”
, baseAddress);
profile.SetPreference(“network.dns.disableIPv6”, true);
var webDriver = new FirefoxDriver(profile);
Last but not least, if your UI tests suddenly stop working for no apparent reason, just make sure your browser is displaying in 100% view mode. What I experienced was that one day the buttons were not clicked anymore and in vertical menu item, the items above the ones I specified were wrongly clicked. I checked if any changes in website or UI test caused these problems. I even checked if any windows updates for IE were installed. After much pain and suffering, I accidentally noticed the browser was running in 105% view mode. Next time, I will have a little more faith in our codebase. 🙂