← Blog

"Selenium Series #11: Actions Class — Mouse Interactions, Drag-Drop and Keyboard Shortcuts"

The Actions class handles everything beyond basic click and type — hover menus, drag and drop, right-click context menus, double-click, click-and-hold, and complex keyboard shortcuts.

reading now
views
comments

Series Navigation

Part 10: JavaScriptExecutor

Part 12: Screenshots, File Downloads and Test Evidence


The Actions Builder Pattern

Actions builds a chain of interactions and executes them together with .perform():

import org.openqa.selenium.interactions.Actions;

Actions actions = new Actions(driver);

// Build and execute a chain
actions.moveToElement(menuItem)   // hover
       .click()                   // click
       .perform();                // execute the chain

Mouse Hover — Opening Dropdown Menus

Actions actions = new Actions(driver);

// Hover over an element (triggers CSS :hover)
WebElement navMenu = driver.findElement(By.id("navMenu"));
actions.moveToElement(navMenu).perform();

// Wait for dropdown to appear
WebDriverWait wait = new WebDriverWait(driver, 5);
WebElement dropdown = wait.until(
    ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".dropdown-menu"))
);

// Click the dropdown item
WebElement menuItem = driver.findElement(By.linkText("Profile Settings"));
actions.moveToElement(menuItem).click().perform();

Hover with Offset

// Hover at a specific x,y offset from element's top-left corner
actions.moveToElement(element, 50, 20).perform();

// Hover at absolute page coordinate
actions.moveByOffset(500, 300).perform();

Right-Click (Context Menu)

WebElement rightClickArea = driver.findElement(By.id("rightClickDiv"));

actions.contextClick(rightClickArea).perform();

// The browser context menu appears — interact with it
// (Note: browser's native context menu can't be interacted with via Selenium
// For app-specific context menus, find the menu elements after right-click)
WebElement menuOption = wait.until(
    ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".context-menu-item"))
);
menuOption.click();

Double-Click

WebElement editableCell = driver.findElement(By.cssSelector("td.editable"));
actions.doubleClick(editableCell).perform();

// Verify cell entered edit mode
WebElement cellInput = wait.until(
    ExpectedConditions.visibilityOfElementLocated(By.cssSelector("td.editable input"))
);
cellInput.clear();
cellInput.sendKeys("New value");
cellInput.sendKeys(Keys.ENTER);

Click and Hold

// Click and hold (don't release)
WebElement slider = driver.findElement(By.id("slider-handle"));
actions.clickAndHold(slider).perform();

// Move while holding (drag)
actions.moveByOffset(100, 0).perform(); // move 100px right

// Release
actions.release().perform();

// Or do it all in one chain:
actions.clickAndHold(slider)
       .moveByOffset(100, 0)
       .release()
       .perform();

Drag and Drop

WebElement source = driver.findElement(By.id("draggable"));
WebElement target = driver.findElement(By.id("droppable"));

// Method 1: dragAndDrop
actions.dragAndDrop(source, target).perform();

// Method 2: manual click-hold-move-release (more reliable in some browsers)
actions.clickAndHold(source)
       .moveToElement(target)
       .release(target)
       .perform();

// Method 3: drag by offset in pixels
actions.dragAndDropBy(source, 200, 0).perform(); // drag 200px right

Drag and Drop with JavaScript (More Reliable)

Some drag-and-drop libraries intercept mouse events and don't respond to Selenium's Actions. Use JavaScript simulation:

// Inject a drag-and-drop simulation script
String dragDropScript = """
    function simulateDragDrop(sourceNode, destinationNode) {
        var EVENT_TYPES = {
            DRAG_END: 'dragend',
            DRAG_START: 'dragstart',
            DROP: 'drop'
        };

        function createCustomEvent(type) {
            var event = new CustomEvent(type, { bubbles: true, cancelable: true });
            event.dataTransfer = { data: {}, setData: function(k,v){this.data[k]=v;},
                                   getData: function(k){return this.data[k];} };
            return event;
        }

        sourceNode.dispatchEvent(createCustomEvent(EVENT_TYPES.DRAG_START));
        destinationNode.dispatchEvent(createCustomEvent(EVENT_TYPES.DROP));
        sourceNode.dispatchEvent(createCustomEvent(EVENT_TYPES.DRAG_END));
    }
    simulateDragDrop(arguments[0], arguments[1]);
    """;

WebElement source = driver.findElement(By.id("draggable"));
WebElement target = driver.findElement(By.id("droppable"));
((JavascriptExecutor) driver).executeScript(dragDropScript, source, target);

Keyboard Shortcuts with Actions

Actions actions = new Actions(driver);

// Ctrl+A (select all)
actions.keyDown(Keys.CONTROL)
       .sendKeys("a")
       .keyUp(Keys.CONTROL)
       .perform();

// Ctrl+C (copy)
actions.keyDown(Keys.CONTROL)
       .sendKeys("c")
       .keyUp(Keys.CONTROL)
       .perform();

// Ctrl+V (paste)
WebElement targetField = driver.findElement(By.id("pasteTarget"));
actions.click(targetField)
       .keyDown(Keys.CONTROL)
       .sendKeys("v")
       .keyUp(Keys.CONTROL)
       .perform();

// Ctrl+Shift+I (DevTools — don't actually do this in tests)
actions.keyDown(Keys.CONTROL)
       .keyDown(Keys.SHIFT)
       .sendKeys("i")
       .keyUp(Keys.SHIFT)
       .keyUp(Keys.CONTROL)
       .perform();

// Select text with Shift+End
WebElement input = driver.findElement(By.id("textField"));
input.click();
actions.keyDown(Keys.SHIFT)
       .sendKeys(Keys.END)  // select to end of line
       .keyUp(Keys.SHIFT)
       .perform();

Complex Real-World Example: Resizable Column

@Test
public void testResizableTableColumn() {
    WebDriver driver = getDriver();
    driver.get("https://jqueryui.com/resizable/");

    // Switch to iframe (jQuery UI demos use iframes)
    driver.switchTo().frame(driver.findElement(By.cssSelector(".demo-frame")));

    WebElement resizable = driver.findElement(By.id("resizable"));

    // Get original size
    Dimension originalSize = resizable.getSize();
    System.out.println("Original: " + originalSize.width + "x" + originalSize.height);

    // Find the resize handle (bottom-right corner)
    WebElement handle = driver.findElement(By.cssSelector("#resizable .ui-resizable-se"));

    // Drag the handle to resize
    Actions actions = new Actions(driver);
    actions.clickAndHold(handle)
           .moveByOffset(100, 50)  // expand 100px right, 50px down
           .release()
           .perform();

    // Verify new size
    Dimension newSize = resizable.getSize();
    System.out.println("New size: " + newSize.width + "x" + newSize.height);
    Assert.assertTrue(newSize.width > originalSize.width, "Width should increase");
}

What's Next

In Part 12 we capture screenshots, record test evidence, handle file downloads, and build a complete reporting utility that attaches screenshots to failed test reports.

Discussion

Loading...

Leave a Comment

All comments are reviewed before appearing. No links please.

0 / 1000