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);