Showing posts with label Web Driver. Show all posts
Showing posts with label Web Driver. Show all posts

Saturday, July 04, 2015

Drag and Drop tricks in Selenium

Many of the UI draggable elements can be easily draggable from one place to another place over the web page. 
In some cases though the web element is associated with draggable properties, they won't respond when we do drag action through our selenium code by using Actions class. Below are few of the scenario, which will help you to drag and drop your draggable web elements over the web page.

The draggable elements can be anything with draggable properties associated with. It could be a table header cell or can be draggable div or a frame or etc. Lets take an example of a source element(from which you will start the drag action) and a destination element(at which you will drop by releasing your mouse) as below:
WebDriver driver = new FirefoxDriver();

WebElement fromWebElement =
  driver.findElement(By.cssSelector(".ui-draggable div[title='DragMe']"));
WebElement toWebElement =
  driver.findElement(By.cssSelector(".ui-draggable div[title='DropMe']"));
(1) By using Actions class of Selenium webdriver

Case 1: 

Selenium web driver provides Actions class to do drag and drop actions in the web page.
Actions builder = new Actions(driver);
builder.dragAndDrop(fromWebElement, toWebElement);
This will work for most of the draggable web elements.

Case 2:

In case of some of the draggable web element the below works very well:
Actions builder = new Actions(driver);
Action dragAndDrop =
  builder.clickAndHold(fromWebElement).moveToElement(toWebElement)
    .release(toWebElement).build();
dragAndDrop.perform();
Make sure to call the perform() method at the end like above.

Case 3:

In few website the draggable elements doesn't work with either of the above cases. Then you can try the below:
Actions builder = new Actions(driver);
Action dragAndDrop =
  builder.clickAndHold(fromWebElement).moveToElement(toWebElement, 2, 2)
    .release(toWebElement).build();
dragAndDrop.perform();
You can adjust the xOffset and yOffset values(which is 2 in the above example) as per your requirements

Case 4:

This case is very interesting one which will work anyway for all the types of draggable UI elements in the webpage.
Actions builder = new Actions(driver);
builder.clickAndHold(fromWebElement).moveToElement(toWebElement).perform();
Thread.sleep(2000);// add 2 sec wait
builder.release(toWebElement).build().perform();
In the above code the 2 second wait during the drag and drop action is important. I would suggest use this way only if the above cases are not working for you.

(2) By using Robot class

Case 1:

If any of the above drag and drop actions using selenium doesn't work for you, do the drag and drop using Robot class as below:
Point coordinates1 = fromWebElement.getLocation();
Point coordinates2 = toWebElement.getLocation();

Robot robot = new Robot();

robot.mouseMove(coordinates1.getX(), coordinates1.getY());
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseMove(coordinates2.getX(), coordinates2.getY());
robot.mouseRelease(InputEvent.BUTTON1_MASK);
Thread.sleep(2000);// Give some wait if required(e.g. here 2 sec wait)
Hope it helps you! 

Friday, May 08, 2015

Dealing with <object> tags in selenium webdriver

Many web pages uses <object> tags for embedded object within an HTML document. This element is mainly used to embed SVG elements, multimedia, Java applets, Flash etc.
Many web pages also use the <object> tag to embed another webpage or frames into the HTML document.

Though <object> tags looks slimilar to <iframe>, it won't work if you do switch frame by webdriver (e.g. driver.switchTo().frame(objIDorIndex);)

Here are few scenarios that you can handle using selenium webdriver with javascript/jQuery.

Example - 1: 
widthmm=90.48768097536195 heightmm=49.38127063754128 ... ...
Example - 2: 

Content HTML Viewer
(Case 1) In example-1, if you want to click on a "g" elements of SVG element
WebElement objectTag= findElement(By.xpath("//div[@id='imageholder']//object"));
((JavascriptExecutor) driver).executeScript("return (arguments[0].contentDocument.getElementsByTagName('g')[0]).click()", objectTag);
(Case 2) In example-2, if you want to get the title for assertion, then try as an example given below
List<WebElement> objects = findElements(By.xpath("//div[@class='contentViewer']//object"));
String objectId = objects.get(0).getAttribute("id");
WebDriver driver = getDriver();
JavascriptExecutor js = (JavascriptExecutor) driver;
String text = (String) js.executeScript("return (((document.getElementById('" + objectId + "')).contentDocument).getElementsByClassName('titleText')[0]).innerHTML");
getDriver().switchTo().defaultContent();
(Case 3) In example-2, if you want to get any specific attribute, then try something like below
List<WebElement> objects = findElements(By.xpath("//div[@class='contentViewer']//object"));
String objectId = objects.get(0).getAttribute("id");
WebElement objectTag = findElement(By.id(objectId));
String btnTitle = ((JavascriptExecutor) driver).executeScript("return arguments[0].contentDocument.getElementById('closeText').getAttribute('title')", objectTag).toString();
Assert.assertEquals(btnTitle, "Cancel to close");
(Case 4) In example-2, if you want to do any action inside the iFrame, you can use as below given example
WebElement btnDone = (WebElement) js.executeScript("return ((((document.getElementById('" + objectId
            + "')).contentDocument).getElementsByTagName('iFrame')[0]).getElementById('done'))");
btnDone.click();
Note: I have just gave few examples actions w.r.t my example html code snippet. By referring the above examples you do actions inside <object> tag as per your requirements

Sunday, May 03, 2015

Scroll pages in Selenium Webdriver

Most of the cases Selenium automatically calls the javascript "scrollIntoView" function on any element that you try to interact with. If you know an element exists at the bottom of the page then doing anything with that element (including getting an attribute or hovering over it, etc) will cause the page to scroll.

If the above doesn't work, please do either of the followings:

Scroll to a WebElement:
WebElement element = driver.findElement(By.id("navPanel"));
JavascriptExecutor jsexecutor = (JavascriptExecutor) driver;
jsexecutor.executeScript("arguments[0].scrollIntoView();", element);
(Or)
WebElement element = driver.findElement(By.id("navPanel"));
Coordinates coordinate = ((Locatable) element).getCoordinates();
coordinate.onPage();
coordinate.inViewPort();
(Or)
Point point = element.getLocation();
((JavascriptExecutor) driver).executeScript("return window.title;");
Thread.sleep(6000);
((JavascriptExecutor) driver).executeScript("window.scrollBy(0," + (point.getY()) + ");");

Scroll up the web page:
JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;
jsExecutor.executeScript("scroll(300, 0)"); 
// here x value(horizontal value)'300' can be changed as needed
Scroll down the web page:
JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;
jsExecutor.executeScript("scroll(0, 300)"); 
// here y value(vertical value) '300' can be changed as needed
Scroll to end/bottom of page:
Actions actions = new Actions(driver);
actions.keyDown(Keys.CONTROL).sendKeys(Keys.END).perform();
(Or)
JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;  
jsExecutor.executeScript("window.scrollTo(0,Math.max(document.documentElement.scrollHeight,document.body.scrollHeight,document.documentElement.clientHeight));");
(Or)
JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;
for (int second = 0;; second++) {
  if(second >=60){
    break;
  }
  jsExecutor.executeScript("window.scrollBy(0,750)", ""); 
  Thread.sleep(3000);
}
//y value(vertical length) '750' can be changed as needed

Wednesday, August 20, 2014

Data driven testing in Selenium WebDriver with TestNG using Excel

When we want to implement data driven testing using Excel, you need to understand how to read from an Excel sheet. You can read an Excel sheet by using Apache POI

You need to use the below jars for reading from an excel file. 
  1. poi-3.7-20101029.jar
  2. poi-ooxml-3.7-20101029.jar
  3. poi-ooxml-schemas-3.7-20101029.jar
  4. xmlbeans-2.3.0.jar
  5. dom4j-1.6.1.jar
I am using Apache POI 3.7 but you can download the latest jars from downloads page of Apache POI(http://poi.apache.org/download.html). Make sure you have added all the above jars to your project build path.

An example excel file(either .xslx or .xls formats) is given below:



The below self explanatory class is used for reading any cell of an excel sheet.
//Keywords class DataDrivenExcel.java
package example.aks.data.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * This class allows us the use of an Excel spreadsheet to provide input data to
 * a test or set of tests.
 * 
 * @author A. K. Sahu
 * 
 */

public class DataDrivenExcel {

 private Workbook wb;
 private Sheet ws;

 /**
  * Opens a excel sheet
  * 
  * @param fileName
  *            name of the file where you want data
  * @param sheetName
  *            name of the sheet in the excel file
  */
 public DataDrivenExcel(String fileName, String sheetName) {
  try {
   if (fileName.indexOf("xlsx") < 0) { //for .xls format
    wb = new HSSFWorkbook(new FileInputStream(new File(fileName)));
    ws = wb.getSheet(sheetName);
   } else { //for .xlsx format
    wb = new XSSFWorkbook(fileName);
    ws = (XSSFSheet) wb.getSheet(sheetName);
   }
  } catch (IOException io) {
   System.err.println("Invalid file '" + fileName
     + "' or incorrect sheet '" + sheetName
     + "', enter a valid one");
  }
 }

 /**
  * Gets a cell value from the opened sheet
  * 
  * @param rowIndex
  *            starting with 0 index
  * @param columnIndex
  *            starting with 0 index
  * @return
  */
 public String getCell(int rowIndex, int columnIndex) {
  Cell cell = null;
  try {
    cell = ws.getRow(rowIndex).getCell(columnIndex);
  } catch (Exception e) {
   System.err.println("The cell with row '" + rowIndex + "' and column '"
     + columnIndex + "' doesn't exist in the sheet");
  }
  return new DataFormatter().formatCellValue(cell);
 }
}
The test class that uses the above keywords of the DataDrivenExcel class looks like below which is also self explanatory.
//Usage in the TestNG test class DataDrivenTest.java
package example.aks.data.test;

import java.util.ArrayList;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import example.aks.data.util.DataDrivenExcel;

/**
 * This class explains the usage of data driven excel
 * 
 * @author A. K. Sahu
 * 
 */
public class DataDrivenTest {

 @DataProvider(name = "loginToAppWithAllRoles")
 public Object[][] getLoginDataForAllRoles() throws Exception {

  DataDrivenExcel userData = new DataDrivenExcel(
    "D:/workspace/DataDriven/data/SampleExcel.xlsx", "Sheet1");

  ArrayList<Object> dataList = new ArrayList<Object>();

  int i = 1;// excluding header row
  int totalRows = 6;
  while (i < totalRows) {
   System.out.println("loginToAppWithAllRoles : line : " + i);

   Object[] dataLine = new Object[4];
   dataLine[0] = userData.getCell(i, 0);
   dataLine[1] = userData.getCell(i, 1);
   dataLine[2] = userData.getCell(i, 2);
   dataLine[3] = userData.getCell(i, 3);

   dataList.add(dataLine);

   i++;
  }

  Object[][] data = new Object[dataList.size()][];
  for (i = 0; i < dataList.size(); i++)
   data[i] = dataList.get(i);

  return data;
 }

 @Test(dataProvider = "loginToAppWithAllRoles", 
       description = "Login with different roles")
 public void testLogin(String userID, String username, String password,
   String role) {

  WebDriver driver = new FirefoxDriver();

  driver.get("http://yoursiteurl.com");

  // Do required actions using the input data, i am just printing here
  System.out.println("userID:" + userID);
  System.out.println("username:" + username);
  System.out.println("password:" + password);
  System.out.println("role:" + role);

  driver.quit();
 }
}
Similarly, you can use an excel file with .xls format.
Important Note: 
In the above test class we used
Object[] dataLine = new Object[4];
Number here should match with the number of parameters for the test case that using this dataprovider.

The  output after executing the tests looks like below:
TestNG Console

Console output

Note: While you are running the tests if you encounter any problem recheck about the below:
  1. Make sure all the above mentioned jars are added to your build path.
  2. The object size defined in the data provider is equal to the number of parameters defined in the test method.
  3. You are reading an existing cell value with a valid row and column index.

Thursday, June 26, 2014

Page Refresh in Selenium WebDriver

There are many ways that we can refresh a web page in Selenium Webdriver tests. Here are listed some of them: 
1) Using refresh() method of WebDriver
driver.navigate().refresh();
This is most commonly used method. 
2) Using F5 key
driver.findElement(By.name("q")).sendKeys(Keys.F5);
This is also commonly used method. We must use it in any text field of the web page as it uses Send keys method. 
3) Using Actions class of WebDriver
Actions actions = new Actions(driver);
actions.keyDown(Keys.CONTROL).sendKeys(Keys.F5).perform();
4) Using jQuery
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("history.go(0)");
5) Using navigate( ).to( ) method of WebDriver
driver.navigate().to(driver.getCurrentUrl());
6) Using ASCII code
driver.findElement(By.name("q")).sendKeys("\uE035");

Navigate Back, Forward and to an Url in Selenium Webdriver

Below scenarios explains how we can navigate across the browser for various web pages.
WebDriver driver = new FirefoxDriver();
driver.get("http://aksahu.blogspot.in/");

Navigate to an Url:
driver.navigate().to("http://knowledgebase-wiki.appspot.com/");
This navigates the page to "http://knowledgebase-wiki.appspot.com/"

Navigate Back:
driver.navigate().back();
This navigates back to the previous page "http://aksahu.blogspot.in/"

Navigate Forward:
driver.navigate().forward();
This navigates the page forward to "http://knowledgebase-wiki.appspot.com/"

Sunday, March 16, 2014

Switch between windows or tabs in Selenium Webdriver

Please refer the below set of code to understand how can we switch between different windows in Selenium. Open a web page:
WebDriver driver = new FirefoxDriver();
driver.get("http://aksahu.blogspot.in/");
Open a new window:
WebElement elemLink = driver.findElement(By.linkText("Web Driver"));
Actions actions = new Actions(driver);
actions.moveToElement(elemLink);
actions.contextClick(elemLink).sendKeys(Keys.ARROW_DOWN)
  .sendKeys(Keys.ARROW_DOWN).sendKeys(Keys.ENTER).build()
  .perform();
For opening in a new tab/window see the post Open in new Tab or new Window in Selenium Webdriver

Switch between two tabs or windows:

(1) 
If you want to switch to a specific window, see below:
String windowHandle = driver.getWindowHandle();

Now if you want to switch to second windows use the below code:
for(String winHandle : driver.getWindowHandles()){
    driver.switchTo().window(winHandle);
}
Switch to the parent window:
driver.switchTo().window(windowHandle);

(2)
Or, simply you can do as below to switch between two tabs or windows:
ArrayList tabs = new ArrayList (driver.getWindowHandles());

//Switch to new window
driver.switchTo().window(tabs.get(1));
driver.close();//do some action in new window(2nd tab)

//Switch to main/parent window
driver.switchTo().window(tabs.get(0));
driver.getTitle();//do some action in main window(1st tab)

Saturday, March 15, 2014

Open in new Tab or new Window in Selenium Webdriver

New Tab:
Use the below code to complete the action in a new tab.
WebDriver driver = new FirefoxDriver();
driver.get("http://aksahu.blogspot.in/");
You can  do by either of the below ways
driver.findElement(By.linkText("Tips & Tricks")).sendKeys(Keys.CONTROL + "t");
Or
WebElement aLink = driver.findElement(By.linkText("Tips & Tricks"));
Actions actions = new Actions(driver);
actions.moveToElement(aLink);
actions.contextClick(aLink)
       .sendKeys(Keys.ARROW_DOWN)
       .sendKeys(Keys.ENTER).build().perform();

New Window:
Use the below code to complete the action in a new window.
WebDriver driver = new FirefoxDriver();
driver.get("http://aksahu.blogspot.in/");
Open a web page in a new window:
String script = "var d=document,a=d.createElement('a');a.target='_blank';a.href='%s';a.innerHTML='.';d.body.appendChild(a);return a";
Object element = ((JavascriptExecutor) driver).executeScript(String.format(script, "http://aksahu.blogspot.in/"));
if (element instanceof WebElement) {
    WebElement anchor = (WebElement) element;
    anchor.click();
    ((JavascriptExecutor) driver).executeScript("var a=arguments[0];a.parentNode.removeChild(a);", anchor);
} else {
     throw new JavaScriptException(element, "Unable to open Window", 1);
}
Open a link in a new window:
WebElement elemLink = driver.findElement(By.linkText("Web Driver"));
Actions actions = new Actions(driver);
actions.moveToElement(elemLink);
actions.contextClick(elemLink)
       .sendKeys(Keys.ARROW_DOWN)
       .sendKeys(Keys.ARROW_DOWN)
       .sendKeys(Keys.ENTER).build().perform();

Wednesday, February 19, 2014

Maximize and Resize browser window in Selenium Webdriver

Maximize browser window:
You can maximize your current browser window by simply calling the maximize() method of WebDriver as below:
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
Sometimes the above doesn't work in some versions of browsers like chrome. So you can use below code alternatively:
Point targetPosition = new Point(0, 0);
driver.manage().window().setPosition(targetPosition);

String w = "return screen.availWidth";
String h = "return screen.availHeight";
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver;
int width = ((Long) javascriptExecutor.executeScript(w)).intValue();
int height = ((Long) javascriptExecutor.executeScript(h))
  .intValue();
Dimension targetSize = new Dimension(width, height);

driver.manage().window().setSize(targetSize);

Resize browser window:
Sometimes in the test we need to resize the browser window to a certain window size. In such cases we can use the below to do:
driver.manage().window().setSize(new Dimension(320, 480));

Friday, January 03, 2014

Selenium tricks for CSS and Xpath locators

In this post you will learn some CSS rules and how to use CSS selectors and Xpath locators in Selenium.

(1) Id:
An element's id is defined as "[@id='idName']" in Xpath but "#idName" in CSS.
For example, a 'div' element with id 'panel' will be represented as below:
In Xpath locator
//div[@id='panel']
In CSS selector
css=div#panel

(2) Class:
An element's class is defined as "[@class='className']" in Xpath but ".className" in CSS.  
For example, a 'div' element with class 'panelClass' will be represented as below:
In Xpath locator
//div[@class='panelClass']
In CSS selector
css=div.panelClass
For element with multiple class we need to separate with space(" ") in Xpath and dot(".") in case of CSS. See below example,
In Xpath locator
//div[@class='panelClass1 panelClass2']
In CSS selector
css=div.panelClass1.panelClass2

(3) Any Attributes:
For selecting an element by its any of the attribute(say "name" is an attribute of a 'div' element and "type" in an "input" element) is given below:
In Xpath locator
//div[@name='continue']
//input[@type='button'] 
In CSS selector
css=div[name='continue']
css=input[type='button'] 

(4) Direct Child:
A direct child of an element is denoted as "/" in Xpath and ">" in CSS selector. See the example below for a direct child "li" for a "ul" element:
In Xpath locator
//ul/li
In CSS selector
css=ul > li

(5) Child or Subchild:
A direct child of an element is denoted as "//" in Xpath and a wehite-space(" ") in CSS selector. See the example below for a child/subchild "li" for a "ul" element:
In Xpath locator
//ul//li
In CSS selector
css=ul li
Note that "ul li" and "ul > li" are different. If you are confusing please go through this article.

(6) nth Child:
For finding 'nth' child, in Xpath we denote as "[n]" and in CSS we denote as ":nth-of-type(n)". See the below example,
  1. Coffee
  2. Tea
  3. Milk
  4. Soup
  5. Soft Drinks
In Xpath locator
//ul[@id='drinks']/li[5]
In CSS selector
css=ul#drinks li:nth-of-type(5)
Also you can use ":nth-child" but the difference between ":nth-child" and ":nth-of-type(n)" is:
li:nth-child(2)
This means, select an element if It is a paragraph element and the second child of a parent.

li:nth-of-type(2)
This means, select the second paragraph child of a parent. This is less conditional.

See here for more details on difference between the above two.

If we want to select the "fifth li element" (Soft Drinks) in this list, we can use the nth-of-type, which will find the fifth li in the list.
css=ul#drinks li:nth-of-type(5)
On the other hand, if we want to get the "fifth element" only if it is a li element, we can use a filtered nth-child which will select again (Soft Drinks) here.
css=ul#drinks li:nth-child(5)
(7) Parent of an element:
Parent of an element can be represented as "/.." in Xpath and ":parent" in CSS selectors. For example, if you want to indicate parent of the list item of class 'blue'
  • first
  • second
  • third
  • fourth
  • fifth
In Xpath locator
//li[@class='blue']/..
In CSS selector
css=li.blue:parent

(8) Next Sibling:
Next sibling is nothing but next adjacent element which is inside the same parent on the page. An adjacent sibling combinator selector allows you to select an element that is directly after another specific element. For example, If you want to select the sibling of "li" element with class "blue" which is 'second' list item,
In Xpath locator
//li[@class='blue']/../li[2]
In CSS selector
css=li.blue + li
Similarly, if you want to indicate 'third' list item, see the below
In Xpath locator
//li[@class='blue']/../li[3]
In CSS selector
css=li.blue + li + li

(9) Match by Innertext:
There is a javascript methodcontains() which can be used to check the inner text of a web element. For example a link with text "Sign in"
In Xpath locator
//a[contains(text(),'Sign in')]
or
//a[contains(string(),'Sign in')] 
In CSS selector
css=a:contains('Sign in')

(10) Match by Sub-string:
This is interesting and is described below. With this we can match strings with its partial text. E.g. prefix, suffix or any pattern(sub-string)
(i) Match a Sub-string(pattern):
Taking an example of a 'div' with an 'id' that contains the text "pattern"
...
In Xpath locator, we need to use "contains()" to match a sub-string
//div[contains(@id,'pattern')]
In CSS selector, we need to use "*=" for matching a sub-string
css=div[id*='pattern']

(ii) Match a prefix:
Taking an example of a 'div' with an 'id' that starts with the text "prefixString"
...
In Xpath locator, we need to use "starts-with" to match a prefix
//div[starts-with(@id,"prefixString")]
In CSS selector, we need to use "^=" for matching a prefix
css=div[id^='prefixString']

(iii) Match a suffix:
Taking an example of a 'div' with an 'id' that starts with the text "suffixString"
...
In Xpath locator, we need to use "ends-with" to match a suffix Note that "ends-with()" is a standard XPath 2.0 function only, it won't work if you are using Xpath 1.0 engine
//div[ends-with(@id,"suffixString")]
In CSS selector, we need to use "$=" for matching a suffix
css=div[id$='suffixString']
The summary of sub-string match is listed out in the following table:
Match a Sub-string Match a Prefix Match a Suffix
Xpath contains() starts-with() ends-with()
CSS *= ^= $=

Sunday, December 22, 2013

Mouse hover in Selenium WebDriver

In some web applications we need to mouse hover on one element to make visible of another element. In those cases we need to mouse over on first element before performing any action on second element.

For example, when we mouse hover on certain menus, the sub-menus appears. In such cases we need to use the following ways to hover on web elements:

  1. Using Actions class:
  2. We can use WebDriver's Actions class to perform hover action as below:
    Actions actions = new Actions(driver);
    WebElement mainMenu = driver.findElement(By.cssSelector("#headerMenu"));
    actions.moveToElement(mainMenu);
    
    WebElement subMenu = driver.findElement(By.cssSelector("#headerMenu .subMenu"));
    actions.moveToElement(subMenu);
    actions.click();
    
    actions.perform();
    
    Don't forget to call 'perform()' method. This action won't complete unless you call perform().

  3. Using JQuery:
  4. You can use JQuery selector with mouseover() function as below:
    String aJQueryString = "jQuery(\"#headerMenu\").mouseover()"; 
    WebElement element = findElementByJQuery(aJQueryString);
    
    For understanding "findElementByJQuery(aJQueryString)" method and use please go through my post "Finding web elements by executing JQuery script".


  5. Using Robot:
  6. You can use Robot class to find out location of the web element in the screen and then by hover on it as below:
    /**
     * Mouse overs on the element by its locator by
     * 
     * @param by
     *            a locator e.g. xpath, css, name, id, class name etc
     */
    public void mouseOverOnElementUsingRobot(By by) {
     try {
      Point coordinates = driver.findElement(by).getLocation();
      Robot robot = new Robot();
      robot.mouseMove(coordinates.getX(), coordinates.getY() + 60);
      /*
       * WebDriver provide document coordinates, where as Robot class is
       * based on Screen coordinates, so I have added +60 to compensate
       * the browser header. You can even adjust if needed.
       */
    
     } catch (AWTException e) {
      log.error("Failed to mouseover on the element '" + by + "'. " + e);
     }
    }
    

Drag and Drop in Selenium WebDriver

Now we can perform Drag and Drop actions in WebDriver using Actions class. Below is the code for this:
Actions builder = new Actions(driver);
builder.dragAndDrop(source, target);
Here 'source' is the source(from element) web element and 'target' is the target(to element) web element. 
Or
/**
 * Drags the web element fromWebElement and drop at web element
 * toWebElement
 * 
 * @param fromWebElement
 * @param toWebElement
 */
public void dragAndDrop(WebElement fromWebElement, WebElement toWebElement) {
 Actions builder = new Actions(driver);

 Action dragAndDrop = builder.clickAndHold(fromWebElement)
   .moveToElement(toWebElement).release(toWebElement).build();

 dragAndDrop.perform();
}
Please visit here for more details.

Using robot:
/**
 * Drags the web element fromWebElement and drop at web element
 * toWebElement
 * 
 * @param fromWebElement
 * @param toWebElement
 */
public void dragAndDrop(WebElement fromWebElement, WebElement toWebElement) {
 Point coordinates1 = fromWebElement.getLocation();
 Point coordinates2 = toWebElement.getLocation();

 Robot robot = new Robot();

 robot.mouseMove(coordinates1.getX(), coordinates1.getY());
 robot.mousePress(InputEvent.BUTTON1_MASK);
 robot.mouseMove(coordinates2.getX(), coordinates2.getY());
 robot.mouseRelease(InputEvent.BUTTON1_MASK);

}
For more details on mouse actions in Robot please visit here
For more tricks on drag and drop actions please visit my post Drag and Drop tricks in Selenium

Saturday, December 21, 2013

Format string for locators

There are many locators for web elements which are of same kind, only they vary with a small difference in index or string such as 
"//div[@id='one']/span[text()='jack']" and 
"//div[@id='one']/span[text()='john']"

For these web elements we should find a common locator with an input span text.
Let's take an example of a web element,
  1. Coffee
  2. Tea
  3. Milk
  4. Soup
  5. Soft Drinks
The locator for the above list items 'Soft Drinks' can be represented as below:
private final String DRINK_ITEM = "ul#drinks li:nth-of-type(5)";// using CSS selector
or
private final String DRINK_ITEM = "//ul[@id='drinks']/li[5]";// using Xpath
For finding 5th 'li' item we can directly use the above locator, but when we want to use 2nd 'li' item or some other item or all 'li' items at a time, then we need to represent the locator in a common way.
  • By direct use: 
For a list item,
WebElement element= driver.findElement(By.xpath(DRINK_ITEM));
element.doSomething();
Or, for all list items,
for (int i = 1; i < count; i++) {
 WebElement element = driver.findElement(By.xpath("//ul[@id='drinks']/li[" + i + "]"));
 element.doSomething();
}
  • By formatting the locator:
For a list item,
String drinkItem = String.format(DRINK_ITEM, 5);
WebElement element = driver.findElement(By.xpath(drinkItem));
element.doSomething();
For multiple list items,
for (int i = 1; i < count; i++) {
 String drinkItem = String.format(DRINK_ITEM, i);
 WebElement element = driver.findElement(By.xpath(drinkItem));
 element.doSomething();
}
If you are still not clear about how to use format string, please see the below examples:
private final String GRID_TABLE_VIEW = "div#panel2content div.table.%s";
private final String RESULT_TABLE_VIEW = "//div[@id='panel1content']//div[%d]/span[text()='%s']";
private final String SPACE_TOGGLE_MENU_OPTION = "ul#spacing_toggle li:nth-of-type(%d)";

String gridTableView = String.format(GRID_TABLE_VIEW, "filterByName");
String resultTableView = String.format(RESULT_TABLE_VIEW, 2, "bill");
String spaceToggleMenuOption = String.format(SPACE_TOGGLE_MENU_OPTION, 3);

/** It will print "div#panel2content div.table.filterByName" */
System.out.println(gridTableView);

/** It will print "//div[@id='panel1content']//div[2]/span[text()='bill']" */
System.out.println(resultTableView);

/** It will print "ul#spacing_toggle li:nth-of-type(3)" */
System.out.println(spaceToggleMenuOption);

Finding web elements by executing JQuery script

WebDriver provides findElement(By by) to find elements by selectors such as Xpath, CSS, name, id, class name etc. Similar way, we can use JQuery expression to select elements and traverse through the DOM tree. 
Here is a simple way to findout, 
For an input element with class 'spbtn' of a parent element with id 'myDiv', we can use the below code to find the web element:
String jQuerySelector = "'#myDiv input.spbtn'";
WebElement webElement = (WebElement) ((JavascriptExecutor) getDriver()).executeScript("return $(" + jQuerySelector+ ").get(0);");
In the other way, we can use the following code which uses a proper wait with optimized way to find out the element. The method throws NoSuchElementException exception if there is no element with this JQuery selector.
/**
 * Finds an element by executing the given jQuery statement
 * jQueryScript
 * 
 * @param jQueryScript
 *            a JQuery Script
 * @return WebElement that is described by that jQuery statement
 *         jQueryScript, if not found, returns null.
 */
public WebElement findElementByJQuery(final String jQueryScript) {
 WebElement element = null;

 Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
   .withTimeout(timeoutSeconds, TimeUnit.SECONDS)
   .pollingEvery(50, TimeUnit.MILLISECONDS)
   .ignoring(NoSuchElementException.class);
 try {
  element = wait.until(new Function<WebDriver, WebElement>() {
   @Override
   public WebElement apply(WebDriver d) {
    String script = "return " + jQueryScript + ".get(0);";
    JavascriptExecutor jse = (JavascriptExecutor) d;
    WebElement webElement = (WebElement) jse
      .executeScript(script);
    return webElement;
   }
  });
 } catch (Exception e) {
  log.error("Failed to find the element by executing JQuery script '"
    + jQueryScript + "'." + e);
 }
 return element;
}
Usage of the above method:
For an element with JQuery selector '#myDiv input.spbtn'
String aJQueryString = "jQuery(\"div.sorted\")";//To get the element
String aJQueryString = "jQuery(\"div.sorted\").parent()";//To get parent of the element
String aJQueryString = "jQuery(\"div.sorted\").mouseover()";//To mouseover on the element

WebElement element = findElementByJQuery(aJQueryString);
Similar way you can use other JQuery functions to work with web elements.

To find all elements with the given JQuery selector. This is similar to findElements(By by) of WebDriver.
/**
 * Find all the elements by executing the given jQuery statement
 * jQueryScript
 * 
 * @param jQueryScript
 *            a JQuery Script 
 * @return WebElement that is described by that jQuery statement
 *         jQueryScript, if not found, returns null.
 */
public List<WebElement> findElementsByJQuery(final String jQueryScript) {
 List<WebElement> elements = null;

 Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
   .withTimeout(timeoutSeconds, TimeUnit.SECONDS)
   .pollingEvery(50, TimeUnit.MILLISECONDS)
   .ignoring(NoSuchElementException.class);
 try {
  elements = wait.until(new Function<WebDriver, List<WebElement>>() {
   @Override
   public List<WebElement> apply(WebDriver d) {
    List<WebElement> webElements = new ArrayList<WebElement>();
    for (int i = 0;; i++) {
     String script = "return " + jQueryScript + ".get(" + i
       + ");";
     JavascriptExecutor jse = (JavascriptExecutor) d;
     WebElement webElement = (WebElement) jse
       .executeScript(script);
     if (webElement != null) {
      webElements.add(webElement);
     } else {
      break;
     }
    }
    return webElements;
   }
  });
 } catch (Exception e) {
  log.error("Failed to find the elements by executing JQuery script '"
    + jQueryScript + "'." + e);
 }
 return elements;
}

Tuesday, November 26, 2013

Get name of test method in teardown

Sometimes we need name of the test method that has just executed in the tear down method for various purposes such as:
  • If you take screenshot in tear down and want to give last executed method name as a part of screenshot name.
  • May be someone want to track something in the log with the test method information.
  • If you have different classes containing test methods and tear down method, and you want to use test method information in tear down method.
@AfterMethod
public void yourTearDownMethod(ITestResult result) {
  System.out.println("method name:" + result.getMethod().getMethodName();
}
Similar way, you can get other information about the test method by result.getMethod().getXXX()

Saturday, May 11, 2013

Wait in Selenium WebDriver

There are many types of waits in selenium WebDriver.
  1. Thread.sleep()
  2. Implicit Wait
  3. WebDriver Wait
  4. Wait for the Ajax call
  5. Wait for the page to load
1. Thread.sleep()

Here we can't predict the exact required wait time. With this we may need to wait for some extra seconds which decreases performances. These extra seconds became more when we execute multiple tests which increases the overhead. This wait is not recommended and we should not use this in our test.

2. Implicit Wait

This is the wait provided by WebDriver which is used, in general, for waiting for an element. This is recommended and we can use it. For example,
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
When we use this statement, the WebDriver waits for the element(on which next action is performed) till 30 seconds if that is not available immediately. After the timeout period, if the element is not available, it throws NoSuchElementException.
Use of this at the beginning of each test is very profitable and a best practice.
3. WebDriver Wait

This wait waits for a condition. This is also recommended and we can use it. This checks the condition in every 500 milliseconds until it returns true or the timeout. For example,
WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath(xpath)));
Here the condition is "ExpectedConditions.presenceOfElementLocated(By.xpath(xpath))" and this condition is checked in every 500 milliseconds until it is timed out by the timeout specified in timeOutInSeconds.

WebDriver wait is an explicit wait. You can refer here for more about implicit and explicit waits.


4. Wait for the AJAX call to complete

This is also recommended and very useful when we need to wait for some elements on the web page which is updating upon ajax calls.
You can refer the my post "Wait For Ajax call" for how to use this.

5. Wait for page to load

This is also recommended and very useful when you need to wait for a web page to load completely.
You can refer the my post "Wait for Page to load" for how to use this.

Friday, May 10, 2013

Wait for AJAX call to complete in WebDriver

Sometimes in our web application only part of the web page gets loaded upon certain actions, at that time actually an ajax call happens and depending upon the ajax response the page part loads. So in this case we need to wait till the ajax call is completed to test anything on that part of the webpage, if you don't want to do that by waiting for a specific element to be available. Below is the code that waits till the ajax calls completed:
/**
 * Waits until there are no more active ajax connection and until the
 * specified timeoutInSeconds is timeout
 * 
 * @param timeoutInSeconds
 */
public void waitForAjax(long timeoutInSeconds) {
 log.info("Checking active ajax calls by calling jquery.active");
 try {
  if (driver instanceof JavascriptExecutor) {
   JavascriptExecutor jsDriver = (JavascriptExecutor) driver;

   for (int i = 0; i < timeoutInSeconds; i++) {
    Object numberOfAjaxConnections = jsDriver
      .executeScript("return jQuery.active");
    // return should be a number
    if (numberOfAjaxConnections instanceof Long) {
     Long n = (Long) numberOfAjaxConnections;
     log.info("Number of active jquery ajax calls: " + n);
     if (n.longValue() == 0L)
      break;
    }
    Thread.sleep(1000);// 1 second sleep
   }
  } else {
   log.error("Web driver: " + driver
     + " cannot execute javascript");
  }
 } catch (Exception e) {
  log.error("Failed to wait for ajax response: " + e);
 }
}
In this code snippet we are checking the number of active Ajax connections by executing the javascript code jQuery.active then depending upon the result we are waiting for the ajax calls to complete until the timeout specified in timeoutInSeconds paameter

Wait for page to load in WebDriver

Unlike Selenium RC(selenium 1) have waitForPageToLoad method to wait until the page to load, WebDriver(selenium 2) doesn't have any method in the API to wait until the page to load. Here is a way to wait until the page elements load properly.
/**
 * Waits for a page to load for timeOutInSeconds number of
 * seconds.
 * 
 * @param timeOutInSeconds
 */
public void waitForPageToLoad(long timeOutInSeconds) {
 ExpectedCondition expectation = new ExpectedCondition() {
  public Boolean apply(WebDriver driver) {
   return ((JavascriptExecutor) driver).executeScript(
     "return document.readyState").equals("complete");
  }
 };
 try {
  log.info("Waiting for page to load...");
  WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
  wait.until(expectation);
 } catch (Throwable error) {
  log.error("Timeout waiting for Page Load Request to complete after "
    + timeOutInSeconds + " seconds");
  Assert.assertFalse(true,
    "Timeout waiting for Page Load Request to complete.");
 }
}
Here we are checking for the "complete" loading state of the web page by JavascriptExecutor and until that we are waiting till the timeout period specified in timeOutInSeconds parameter.

Tuesday, March 05, 2013

Getting started with WebDriver (Selenium 2)

WebDriver is a automation testing tool for automating testing web applications. It provides tester friendly API which is easy to explore and understand. This tool is not tied to any particular framework such as JUnit or TestNG. It can be used with simple "main" method or any of the unit testing framework such as JUnit or TestNG.

Required downloads: 
  • Download from here the latest version of selenium-server-standalone-x.y.z.jar where x, y and z are digits specifying the version of jar while created by the developers. 
  • Download respective drivers for your browser. Such as FirefoxDriver for Firefox, ChromeDriver for Chrome, InternetExplorerDriver for Internet Explorer and so on.
Quick steps: 
  1. Create a new java project in your favorite IDE 
  2. Add the downloaded jar file into your project build-path. 
  3. Make sure the browser you are selecting to run is installed in your machine.
  4. Copy and paste the following example to execute your first example on WebDriver.
Example Test:

In my example below i have chosen Firefox browser. Here i have not used any framework to execute my test, i have used simple "main" method to execute. The example is self explanatory by its comments.


package com.example.tests;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;

public class GoogleTest {

 public static void main(String[] args) {

  // I have chosen Firefox browser to execute my script
  WebDriver driver = new FirefoxDriver();

  // Go to the Google home page
  driver.get("https://www.google.co.in/");
  
  // Maximize the browser window
  driver.manage().window().maximize();

  // Enter the query string "Cheese"
  WebElement query = driver.findElement(By.name("q"));

  // Type 'aksahu blog' in the search field
  query.sendKeys("aksahu blog");
  driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);

  // Click on the 'A. K. Sahu's Blog' link
  WebElement blog = driver.findElement(By.linkText("A. K. Sahu's Blog"));
  blog.click();
  driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

  // Quit the browser
  driver.quit();
 }
}