Thursday, August 27, 2015

Dealing with input fields in Selenium WebDriver

I got few requests from people saying few of the input fields are not clearing the existing data though we do clear using clear() method in WebDriver and few of the inputs doesn't accept single quote('), double quote("), slash(\), double slash(\\) etc. 
Please have a look on below examples for resolving such issues.
Lets take an example input web element as below :
WebDriver driver = new FirefoxDriver();
WebElement element = driver.findElement(By.cssSelector("#addressInput"));
Clear Input Fields in Selenium WebDriver:
For clearing an input filed you can use either of the following ways:

Case: 1
element.clear();
Case: 2
element.click();
element.clear();
Case: 3
String oldValue = element.getAttribute("value");
if (oldValue.length() > 0) {
 element.clear();
}
Case: 4
element.click();
element.sendKeys(Keys.CONTROL + "a");
element.sendKeys(Keys.BACK_SPACE);
Case: 5
oldValue = element.getAttribute("value");
for (int i = 0; i < oldValue.length() * 2; i++) {
 element.click();
 element.sendKeys(Keys.DELETE);
 element.sendKeys(Keys.CONTROL + "a");
 element.sendKeys(Keys.BACK_SPACE);
 element.click();
 if (element.getAttribute("value").length() == 0) {
  break;
 }
}

Enter Text to Input Fields in Selenium WebDriver:
For entering various types of inputs to an input web element you can use the following approaches:

Case: 1 - Normal Text
element.sendKeys("Some Text");
Case: 2 - Single quote
element.sendKeys("'");// single quote
Sometimes if you try to enter single quote('), it may not enter if you keyboard setting in the system is changes. For example some smart systems enters 2 single quotes on pressing once or sometimes 2 single quotes shown only after pressing 2 times on the single quote key(i.e. on first time press it won't show a single quote). In such cases try using 2 single quotes as your input to input web elements
element.sendKeys("''");
Case: 3 - Double quote
element.sendKeys("\"");// double quote

// similar to above issue for single quote, same applies to double quotes
element.sendKeys("\"\"'"); 
Case: 4 - Single Slash
element.sendKeys("\\");// single slash(\)
Case: 5 - Double Slash
element.sendKeys("\\\\");// double slash(\\) 
Case: 6 - Special Characters
element.sendKeys("!@#$%^&*()_+}?");// special characters
Case: 7 - Scripts
element.sendKeys("<script>alert('Hello');</script>");// script

Hope this helps!

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.