Thursday, February 07, 2013

Custom Wait For - Selenium

Have you been in the following situations:

- Selenium driver fails to find an element because the web page uses AJAX
- The web element is present but selenium driver fails to find the element intermittently

These were two situations which prompted me to write my own custom WaitFor class which has two methods:

- Wait for a javascript code to execute until a specified time-out
- Check if element is present until a specified time-out

Here is the WaitFor Class:
(I did see these solutions in a blog discussions or forum. As soon as I spot the source, I will reference it).
   
    public class WaitFor
    {
        private bool JSEval(IWebDriver driver, string script)
        {
            object result = ((IJavaScriptExecutor)driver).ExecuteScript(script);
            if (result == null)
            {
                return false;
            }
            else
            {
                return (bool)result;
            }
        }

        public void JSWait(IWebDriver driver, string script, long timeout)
        {
            int interval = 500;
            long waited = 0;
            while (!JSEval(driver,script) && waited < timeout)
            {
                Thread.Sleep(interval);
                waited += interval;
            }
        }

        private bool IsElementPresent(IWebDriver driver, By by)
        {
            try
            {
                driver.FindElement(by);
                return true;
            }
            catch (NoSuchElementException)
            {
                return false;
            }
        }
        public void WaitForElementPresent(IWebDriver driver, By by, long timeout)
        {
            int interval = 500;
            long waited = 0;

            while (!IsElementPresent(driver,by) && waited < timeout)
            {
                Thread.Sleep(interval);
                waited += interval;
            }
        }
    }

Here are some of the reasons it works for me:
- Even though Webdriver 2 is supposed to wait for the page to load before checking for element to be present, it does not work always. The WaitForElementPresent method waits for the specified timeout and keeps checking every 500 ms until the timeout expires
- There are multiple ways to wait for AJAX functionality to finish loading, JSWait method above works like a charm for me

Here is how to call these methods from code:

   
        WaitFor ws = new WaitFor();
        // Check for element to be present, wait for 10 seconds before timing out
        ws.WaitForElementPresent(driver, By.XPath("//span[text()='Find Element']"), 10000);
        // Wait for the javascript code to return true before executing the next statement
        ws.JSWait(driver, "return Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack();", 500);
        ws.JSWait(driver, "return !(Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack());", 500);  


Sunday, January 27, 2013

Selenium, FireFox, Firebug and NetExport

How do you get the firebug enabled in Firefox for your selenium tests?

Step 1: Download Firebug and the add-on net
Step 2: Initialize a new FireFoxProfile and add the extensions to the location of the .xpi files for firebug and net export
Step 3: One key statement that I initially missed was:
profile.SetPreference("extensions.firebug.allPagesActivation", "on"); 

Step 4: Enable the auto export property and give the location information

Below is complete code:


               
        [ClassInitialize]
        public void SetupProfile()
        {
            FirefoxProfile profile = new FirefoxProfile();
            try
            {
                profile.AddExtension(@"C:\LocalMachineUser\AppData\Roaming\Mozilla\Firefox\Profiles\0z8cb853.default\extensions\firebug@software.joehewitt.com.xpi");
                profile.AddExtension(@"C:\LocalMachineUser\AppData\Roaming\Mozilla\Firefox\Profiles\0z8cb853.default\extensions\netexport@getfirebug.com.xpi");
            }
            catch (IOException ioe)
            {
                Console.WriteLine("Exception occurred loading the profile files " + ioe.Message); 
            }
            profile.SetPreference("extensions.firebug.currentVersion", "1.11.1");
            profile.SetPreference("extensions.firebug.previousPlacement", 1);
            profile.SetPreference("extensions.firebug.onByDefault", true);
            profile.SetPreference("extensions.firebug.defaultPanelName", "net");
            profile.SetPreference("extensions.firebug.net.enableSites", true);
            profile.SetPreference("extensions.firebug.allPagesActivation", "on"); 
            profile.SetPreference("extensions.firebug.netexport.defaultLogDir", @"D:\TestFiles\_HAR");
            profile.SetPreference("extensions.firebug.netexport.alwaysEnableAutoExport", true);
            driver = new FirefoxDriver(profile);
            baseURL = "https://companyurl";
            verificationErrors = new StringBuilder();
        }