Wednesday, July 3, 2013

How to perform multiple mouse and keyboard actions in Selenium RC and Web Driver

Many applications allow or require a user, to perform multiple or complicated actions, like drag and drop.
In this post we will describe how we can implement, such actions with the use of  SeleniumRC and the Web Driver.

Selenium RC
In the Selenium RC case, a user can perform all the actions upon a selenium instance.
All user interactions are performed sequentially. Some examples are the following:
selenium.dragAndDropToObject(locatorFrom, locatorTo);
selenium.keyDownNative (thekey.getEvent());

Web Driver
In Web Driver, things are a little more complicating, thus interesting. First of all we will introduce class Actions of the selenium (package org.openqa.selenium.interactions).
The Actions class is user-facing API for emulating complex user gestures. Web Driver users can use this class to simulate usage of keyboard or mouse events.
The Actions class contains the keyboard and mouse related actions. For example:
 click(WebElement onElement)  
 clickAndHold(WebElement onElement)
doubleClick()  
 doubleClick(WebElement onElement)
dragAndDropBy(WebElement source, int xOffset,int yOffset) 
 keyDown(Keys theKey) 
 keyDown(WebElement element, Keys theKey)
keyUp(Keys theKey)
keyUp(WebElement element, Keys theKey)
moveByOffset(int xOffset, int yOffset)
In order to use the above mentioned actions the user should do the following
First of all, the user must create an instance Actions class
Actions builder = new Actions(driver);
where driver is a Web Driver instance.

Let us explain all the above, a little...
In the Actions class, the user, can perform one action, by simply calling it into the driver instance, followed by the method perform().
For example, if I wanted to double click somewhere:
Actions builder = new Actions(driver);
driver.doubleclick().perform();
This is ok, in the case that the user wants to perform only one action at a time.
But what happens when a user wants to perform many actions? The obvious way to do it, is to perform these actions sequentially. This is made easier, by the fact that all Actions methods return an Actions object.
builder.clickAndHold(ElementA)
       .moveToElement(ElementB)
       .release(ElementA)
       .keyUp(Keys.CONTROL).perform();
A smoother and cooler way to do the above, would be to wrap all these actions in one method, and just call it.
This can be done with the use of the interface Action. The Action interface only has one action - perform().
Action dropAToB= builder.build();
dropAToB.perform();
 In the above example, we dragged ElementA and dropped it to ElementB, using multiple actions.
As a conclusion, Web Driver wins on points Selenium RC, in terms of simplicity. A selenium user will have to execute all actions separately, and sequentially, whereas, a Web Driver user, will just create an actions-chain, upon the driver instance, and execute all the actions in one line.