WebDriver Tips

Selenium2 (WebDriver) Tips:


* How to to check if an element exists on page to work on it?

      Many a times we come across a situation where we first need to make sure if the element we want to work with (or) an element we want to click on is present on the web page and act on it. This can be done in IDE very easiy by using the command "storeElementPresent" which stores true/false into a variable, we can then check for the returned value and take a decision.
     Unfortunately, we dont have a similar command in WebDriver for this, but we have a work-around to achieve this by using Java's List and WebDriver's findElements method.

Here is how you achieve this:
-> Declare a Variable of type List<WebElement>
-> Call findElements() method by passing By.<some location strategy> and assign this to above List variable
-> Check if the size of List Variable is not zero
-> Procede with the actions on the element.

Sample code:

List<WebElement> elements = driver.findElements(By.id("button1"));
if(elements.size!=0)
   elements.get(0).click();    //OR driver.findElements(By.id("button1")).click();




 * How to switch between multiple windows?

     We can find answer to this question in many forums/blogs online. A very common solution would look like this.


Set<String> allWindows = driver.getWindowHandles();
for(String currentWindow : allWindows){
   driver.switchTo().window(currentWindow);
}

Here, "currentWindow" is a String variable that gets the handle of all windows for each iteration. The statement in for loop simply switches between all windows.

If we want to perform any action within each window the we can add such code/statements in for loop after the above switch statement. Ex: If we want to get the title of each window, here is the code:


Set<String> allWindows = driver.getWindowHandles();
for(String currentWindow : allWindows){
   driver.switchTo().window(currentWindow);
   driver.getTitle();
}

Now, how do we switch back to main/parent window?
We have to first store the parent window handle before switching to any child window, and use the stored window handle to swich back once you finish working with its children.
Here is how to do it.

String parentWindow = driver.getWindowHandle();
 once we finish working with all child window, write the below code wot go back to parent

driver.switchTo().window(parentWindow); 

Remember that we need to close all windows by calling close() (driver.close() ) method while the focus is at a given window.




 * How to switch to a particular window?

The above example just explains how to switch between all window but not tells how to reach a particular window and perform tasks. Example, we have 3 windows and you want to go to 2nd window and do some action, how?

The same above code can be used to reach a last window Or second window (new window) if there are only 2 windows, here is how we do it.

Set<String> allWindows = driver.getWindowHandles();
for(String currentWindow : allWindows){
   driver.switchTo().window(currentWindow);
}
//now the focus or cursor is at last window   
//perform the tasks and switch back to parent window.

The other best solution to switch any window is by using toArray() method. here is how to use it.

driver.switchTo().window((String) driver.getWindowHandles().toArray()[1]);
Here, the toArray()[1] refers to second window as the index starts from zero (parent window)





* How to get rid of opening multiple window? 
OR 
Any alternatives/workaround to work with multiple windows? 

If you do not want to fall into the trap of handing multiple windows, if you hate working with them then there is a work-around.
This is applicable only for the new windows opened by/from anchor tags (<a> tags).

How?
Before clicking on the link, we will first find its attrinute "href" and extract its value. This is a URL that takes you to new window. So insted of clicking on this a tag and going to new page we actually use this extracted URL and navigate to it from the current/parent window itself.

Here is how we do it.

String url = driver.findElement(By.linkText("click")).getAttribute("href");      
driver.get(url);
      //now the new window opens as a new page within the parent window
      //Perform your tasks here   
driver.navigate().back()    //to go back to original page content

This method works best with the pages where we can see full url of the new pages, but it wont work well with the pages who have URL masking.




 * How to switch to an IFrame?

Switching to IFrame/Frame is so easy, it is similar to switching between windows. The command looks like this:

driver.switchTo().frame(1);



 * Dealing with Alerts.

HTML/JavaScript alerts are usually 3 types; they are namely Alerts, Prompts and Confirm Boxes.
WebDriver handles all these 3 types using a single implementation called Alert and its associated methods.

Practically, once an alert (any of the three kinds) pops up, we will store it in an variable of type Alert and the method/statement "driver.switchTo().alert()" returns such an alert which is present on the page.

It looks like this:

Alert alert = driver.switchTo().alert()

And, if its a prompt or confirm box even then the code is same, but with a meaningful variables of type Alert

Alert prompt = driver.switchTo().alert()
Alert confirmBox = driver.switchTo().alert()

Now, we send of consent to alerts by accepting (YES) or dismissing (No) them. The methods accept() and dismiss() will send this to alerts.

They look like this:

alert.accept() //OR alert.dismiss()
prompt.accept() //OR prompt.dismiss()
confirmBox.accept() //OR confirmBox.dismiss()

We can send text to prompt by sendKeys() method:

prompt.sendKeys("Selenium");

Have a look at this complete code sequence:

        driver.findElement(By.id("btnPrompt")).click();
        Alert prompt = driver.switchTo().alert();
        System.out.println(prompt.getText());
        prompt.sendKeys("Selenium");
        prompt.accept();
        //prompt.dismiss();
        System.out.println(driver.findElement(By.id("output")).getText());
       
        driver.findElement(By.id("btnAlert")).click();
        Alert alert = driver.switchTo().alert();
        System.out.println(alert.getText());
        alert.accept();
        //alert.dismiss();
        System.out.println(driver.findElement(By.id("output")).getText());
       
        driver.findElement(By.id("btnConfirm")).click();
        Alert confirm = driver.switchTo().alert();
        System.out.println(confirm.getText());
        confirm.accept();
        //confirm.dismiss();
        System.out.println(driver.findElement(By.id("output")).getText());



 * Working with onFocus and onHover.

     Few html elements get displayed onFocusing/OnHovering other elements, we can not access/work with few elements unless we hover/focus on other elements. In such cases, we can pas the control over to those elements by the help of Actions class.

We will first instantiate the Actions class and pass the drivr as a parameter to the constructor. And then we can pass the focus to an element with the help of a method "moveToElement()" which takes
 web-element as parameter.

Here is the code:

Actions act = new Actions(driver);
act.moveToElement(driver.findElement(By.id("save"))).click().perform();




 * Capturing ScreenShots.

     At many places in the program execution, we would want to take screenshots to know how the app is behaving at a given page/screen, to capture errors/server responses in response to our actions.

This is pretty much simple by using "TakesScreenshot" type and getScreenshotAs() method. Taking screen shot involes 2 steps.

Step1: We capture the screenshot and store it as a file in a variable:

File sShot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);

Step2: Save the captured file to local drive in image format:

FileUtils.copyFile(sShot, new File("D:/abc.jpg"));
OR
FileUtils.copyFile(sShot, new File("D:/"+sShot.getName()));




 * Waits : Waiting for Ajax responses and Regular Page loads.

     Waiting for page to load and waiting for Ajax responses is not provided by WebDriver in direct way as in IDE. Selenium IDE has selenese commands such as clickAndWait and waitFor to deal with regular and Ajax requests. But, with WebDriver we will have to do some work-around to achieve this.

Here is how it is done by using the classes WebDriverWait and ExpectedConditions.
A typical wait statement looks like this:

new WebDriverWait(driver, 60).until(ExpectedConditions.presenceOfElementLocated(By.id("save")));

To understand this, its is actually a combination of 2 statements. One is to instantiate WebDriverWait class by passing driver and wait-time as parameters and second step is calling until() method of above instance and passing a locator strategy which is of type Predicate that returns true.

We can rewrite it as :

WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("save")));
The until method delays the execution until it returns true for a maximum waiting time of 60 seconds, in simple words it waits for an element with id=save to be present in the web page. If the element found in the interim then the execution resumes immediately without having wait for 60 secs.

We can have it wait till an element is visible or invisible ( display : block //or none), till all elemenst with a common location strategy are visible, till an element is click-able etc etc. We can find all these static methods as in ExpectedConditions class.

To name a few:

alertIsPresent()
elementSelectionStateToBe(By locator, boolean selected) 
elementToBeClickable(By locator)
invisibilityOfElementLocated(By locator)
invisibilityOfElementWithText(By locator, java.lang.String text)
not(ExpectedCondition<?> condition)
presenceOfAllElementsLocatedBy(By locator) 
textToBePresentInElement(By locator, java.lang.String text)
titleContains(java.lang.String title)
visibilityOfElementLocated(By locator) 

  
Custom Wait methods:

There are many situations where we want to use our custom wait methods. Many of the real time users write their own methods depending on the requirement.

The ideal wait methos should possess these characterestics:
  • Capable of waiting until timeout and return a custom "Time Out" error message.
  • Should return TRUE immediately after finding the element, should not waste time until max time passed.
  • Should not throw exceptions if element was not found
  • Should be flexible to accept any time units or any maximim time.
  • Should be flexible to accept any "Find And Wait" freequency/Time Interval [Ex: Max Time out is 30 secs and check for every 500 milli secs]

I wrote my own custom wait method below, it can possses some of those I mentioned above. lets look at the code closely.

---------------------------------------------
public static boolean waitForElement(By element, int timeOutInSeconds){
        boolean found = false;
        try{
            int counter=1;
            while(counter<timeOutInSeconds){
                if(driver.findElements(element).size()>0){
                    found = true;
                    break;
                }
                else{
                    Thread.sleep(1000);
                    counter++;
                }
            }
            return found;
        }
        catch(Exception e){
            e.printStackTrace();
            return found;
        }
    }
 ---------------------------------------------

    This method takes two parameters; one is the element/web object and the other is maximum timeout.
The time out should be in seconds and the methos checks if the element is present for every 1 second and repeats the process for 30 times. However, in the meantine if the element is found then the method immediatelt breaks the loop and return TRUE.

For example, if the element if found at 8th attempt (8th second)  then it quits the loop and saves us 22 seconds.