Mouse Actions
Master advanced mouse interactions including hover, right-click, double-click, and complex mouse movements.
Selenium 3 & 4 Medium
Beyond simple clicks, web applications often require hover menus, context menus, and other mouse-based interactions. The Actions API provides complete control over mouse behavior.
Basic Mouse Actions
Common Mouse Actions
Selenium 3 & 4 Stable
import org.openqa.selenium.interactions.Actions;import org.openqa.selenium.WebElement;
Actions actions = new Actions(driver);WebElement element = driver.findElement(By.id("target"));
// Simple clickactions.click(element).perform();
// Double clickactions.doubleClick(element).perform();
// Right-click (context menu)actions.contextClick(element).perform();
// Click and holdactions.clickAndHold(element).perform();
// Release (after clickAndHold)actions.release().perform();
// Move to element (hover)actions.moveToElement(element).perform();from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(driver)element = driver.find_element(By.ID, "target")
# Simple clickactions.click(element).perform()
# Double clickactions.double_click(element).perform()
# Right-click (context menu)actions.context_click(element).perform()
# Click and holdactions.click_and_hold(element).perform()
# Release (after click_and_hold)actions.release().perform()
# Move to element (hover)actions.move_to_element(element).perform()const actions = driver.actions({ async: true });const element = await driver.findElement(By.id('target'));
// Simple clickawait actions.click(element).perform();
// Double clickawait actions.doubleClick(element).perform();
// Right-click (context menu)await actions.contextClick(element).perform();
// Click and holdawait actions.press().perform();
// Releaseawait actions.release().perform();
// Move to element (hover)await actions.move({ origin: element }).perform();using OpenQA.Selenium.Interactions;
Actions actions = new Actions(driver);IWebElement element = driver.FindElement(By.Id("target"));
// Simple clickactions.Click(element).Perform();
// Double clickactions.DoubleClick(element).Perform();
// Right-click (context menu)actions.ContextClick(element).Perform();
// Click and holdactions.ClickAndHold(element).Perform();
// Release (after ClickAndHold)actions.Release().Perform();
// Move to element (hover)actions.MoveToElement(element).Perform();Hover Menus
Many sites use hover-activated dropdown menus:
Interacting with Hover Menus
Selenium 3 & 4 Medium
// Hover over main menu itemWebElement menuItem = driver.findElement(By.id("products-menu"));Actions actions = new Actions(driver);actions.moveToElement(menuItem).perform();
// Wait for submenu to appearWebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));WebElement submenu = wait.until(ExpectedConditions.visibilityOfElementLocated( By.className("dropdown-menu")));
// Click submenu itemWebElement submenuItem = driver.findElement(By.linkText("Laptops"));actions.moveToElement(submenuItem).click().perform();
// Multi-level hover menuWebElement level1 = driver.findElement(By.id("electronics"));WebElement level2 = driver.findElement(By.id("computers"));WebElement level3 = driver.findElement(By.id("laptops"));
actions.moveToElement(level1) .pause(Duration.ofMillis(500)) // Wait for animation .moveToElement(level2) .pause(Duration.ofMillis(500)) .moveToElement(level3) .click() .perform();import time
# Hover over main menu itemmenu_item = driver.find_element(By.ID, "products-menu")actions = ActionChains(driver)actions.move_to_element(menu_item).perform()
# Wait for submenu to appearwait = WebDriverWait(driver, 10)submenu = wait.until(EC.visibility_of_element_located( (By.CLASS_NAME, "dropdown-menu")))
# Click submenu itemsubmenu_item = driver.find_element(By.LINK_TEXT, "Laptops")actions = ActionChains(driver)actions.move_to_element(submenu_item).click().perform()
# Multi-level hover menulevel1 = driver.find_element(By.ID, "electronics")level2 = driver.find_element(By.ID, "computers")level3 = driver.find_element(By.ID, "laptops")
actions = ActionChains(driver)actions.move_to_element(level1) .pause(0.5) .move_to_element(level2) .pause(0.5) .move_to_element(level3) .click() .perform()// Hover over main menu itemconst menuItem = await driver.findElement(By.id('products-menu'));await driver.actions({ async: true }) .move({ origin: menuItem }) .perform();
// Wait for submenu to appearconst submenu = await driver.wait( until.elementLocated(By.className('dropdown-menu')), 10000);
// Click submenu itemconst submenuItem = await driver.findElement(By.linkText('Laptops'));await driver.actions({ async: true }) .move({ origin: submenuItem }) .click() .perform();
// Multi-level hover menuconst level1 = await driver.findElement(By.id('electronics'));const level2 = await driver.findElement(By.id('computers'));const level3 = await driver.findElement(By.id('laptops'));
await driver.actions({ async: true }) .move({ origin: level1 }) .pause(500) .move({ origin: level2 }) .pause(500) .move({ origin: level3 }) .click() .perform();// Hover over main menu itemIWebElement menuItem = driver.FindElement(By.Id("products-menu"));Actions actions = new Actions(driver);actions.MoveToElement(menuItem).Perform();
// Wait for submenu to appearWebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));IWebElement submenu = wait.Until(ExpectedConditions.ElementIsVisible( By.ClassName("dropdown-menu")));
// Click submenu itemIWebElement submenuItem = driver.FindElement(By.LinkText("Laptops"));new Actions(driver).MoveToElement(submenuItem).Click().Perform();
// Multi-level hover menuIWebElement level1 = driver.FindElement(By.Id("electronics"));IWebElement level2 = driver.FindElement(By.Id("computers"));IWebElement level3 = driver.FindElement(By.Id("laptops"));
new Actions(driver) .MoveToElement(level1) .Pause(TimeSpan.FromMilliseconds(500)) .MoveToElement(level2) .Pause(TimeSpan.FromMilliseconds(500)) .MoveToElement(level3) .Click() .Perform();Context Menu (Right-Click)
Right-Click Context Menu
Selenium 3 & 4 Medium
// Right-click to open context menuWebElement target = driver.findElement(By.id("context-area"));Actions actions = new Actions(driver);actions.contextClick(target).perform();
// Wait for context menuWebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));wait.until(ExpectedConditions.visibilityOfElementLocated( By.className("context-menu")));
// Click menu optionWebElement copyOption = driver.findElement( By.xpath("//div[@class='context-menu']//span[text()='Copy']"));copyOption.click();
// Handle browser's native context menu (limited control)// Usually need to interact with custom context menus instead# Right-click to open context menutarget = driver.find_element(By.ID, "context-area")actions = ActionChains(driver)actions.context_click(target).perform()
# Wait for context menuwait = WebDriverWait(driver, 5)wait.until(EC.visibility_of_element_located( (By.CLASS_NAME, "context-menu")))
# Click menu optioncopy_option = driver.find_element( By.XPATH, "//div[@class='context-menu']//span[text()='Copy']")copy_option.click()
# Handle browser's native context menu (limited control)# Usually need to interact with custom context menus instead// Right-click to open context menuconst target = await driver.findElement(By.id('context-area'));await driver.actions({ async: true }) .contextClick(target) .perform();
// Wait for context menuawait driver.wait( until.elementLocated(By.className('context-menu')), 5000);
// Click menu optionconst copyOption = await driver.findElement( By.xpath("//div[@class='context-menu']//span[text()='Copy']"));await copyOption.click();// Right-click to open context menuIWebElement target = driver.FindElement(By.Id("context-area"));Actions actions = new Actions(driver);actions.ContextClick(target).Perform();
// Wait for context menuWebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));wait.Until(ExpectedConditions.ElementIsVisible( By.ClassName("context-menu")));
// Click menu optionIWebElement copyOption = driver.FindElement( By.XPath("//div[@class='context-menu']//span[text()='Copy']"));copyOption.Click();Moving Mouse to Coordinates
Coordinate-Based Mouse Movement
Selenium 3 & 4 Medium
Actions actions = new Actions(driver);
// Move to element with offset from its centerWebElement canvas = driver.findElement(By.id("drawing-canvas"));actions.moveToElement(canvas, 50, 30) // 50px right, 30px down from center .click() .perform();
// Move by offset from current positionactions.moveByOffset(100, 0) // Move 100px right .click() .moveByOffset(0, 50) // Move 50px down .click() .perform();
// Draw a line on canvasactions.moveToElement(canvas, -100, -100) .clickAndHold() .moveByOffset(200, 200) .release() .perform();actions = ActionChains(driver)
# Move to element with offset from its centercanvas = driver.find_element(By.ID, "drawing-canvas")actions.move_to_element_with_offset(canvas, 50, 30) .click() .perform()
# Move by offset from current positionactions = ActionChains(driver)actions.move_by_offset(100, 0) .click() .move_by_offset(0, 50) .click() .perform()
# Draw a line on canvasactions = ActionChains(driver)actions.move_to_element_with_offset(canvas, -100, -100) .click_and_hold() .move_by_offset(200, 200) .release() .perform()// Move to element with offsetconst canvas = await driver.findElement(By.id('drawing-canvas'));await driver.actions({ async: true }) .move({ origin: canvas, x: 50, y: 30 }) .click() .perform();
// Move by offset from current positionawait driver.actions({ async: true }) .move({ x: 100, y: 0 }) .click() .move({ x: 0, y: 50 }) .click() .perform();
// Draw a line on canvasawait driver.actions({ async: true }) .move({ origin: canvas, x: -100, y: -100 }) .press() .move({ x: 200, y: 200 }) .release() .perform();Actions actions = new Actions(driver);
// Move to element with offset from its centerIWebElement canvas = driver.FindElement(By.Id("drawing-canvas"));actions.MoveToElement(canvas, 50, 30) // 50px right, 30px down .Click() .Perform();
// Move by offset from current positionnew Actions(driver) .MoveByOffset(100, 0) // Move 100px right .Click() .MoveByOffset(0, 50) // Move 50px down .Click() .Perform();
// Draw a line on canvasnew Actions(driver) .MoveToElement(canvas, -100, -100) .ClickAndHold() .MoveByOffset(200, 200) .Release() .Perform();Scroll Actions
Selenium 4 added scroll support to the Actions API:
Scroll Actions (Selenium 4)
Selenium 4 Stable
import org.openqa.selenium.interactions.WheelInput;
// Scroll to elementWebElement footer = driver.findElement(By.id("footer"));Actions actions = new Actions(driver);actions.scrollToElement(footer).perform();
// Scroll by amountactions.scrollByAmount(0, 500).perform(); // Scroll down 500pxactions.scrollByAmount(0, -300).perform(); // Scroll up 300px
// Scroll from elementactions.scrollFromOrigin( WheelInput.ScrollOrigin.fromElement(footer), 0, 200 // dx, dy).perform();
// Scroll with viewport originactions.scrollFromOrigin( WheelInput.ScrollOrigin.fromViewport(), 0, 1000).perform();from selenium.webdriver.common.actions.wheel_input import ScrollOrigin
# Scroll to elementfooter = driver.find_element(By.ID, "footer")actions = ActionChains(driver)actions.scroll_to_element(footer).perform()
# Scroll by amountactions = ActionChains(driver)actions.scroll_by_amount(0, 500).perform() # Scroll down 500pxactions.scroll_by_amount(0, -300).perform() # Scroll up 300px
# Scroll from element originscroll_origin = ScrollOrigin.from_element(footer)actions = ActionChains(driver)actions.scroll_from_origin(scroll_origin, 0, 200).perform()
# Scroll from viewport originscroll_origin = ScrollOrigin.from_viewport(100, 100)actions = ActionChains(driver)actions.scroll_from_origin(scroll_origin, 0, 1000).perform()// Scroll to elementconst footer = await driver.findElement(By.id('footer'));await driver.actions({ async: true }) .scroll(0, 0, 0, 500, footer) .perform();
// Note: JavaScript scroll API differs - consider using executeScriptawait driver.executeScript( "arguments[0].scrollIntoView(true);", footer);
// Scroll by amount using JavaScriptawait driver.executeScript("window.scrollBy(0, 500);");// Scroll to elementIWebElement footer = driver.FindElement(By.Id("footer"));new Actions(driver).ScrollToElement(footer).Perform();
// Scroll by amountnew Actions(driver).ScrollByAmount(0, 500).Perform(); // Down 500pxnew Actions(driver).ScrollByAmount(0, -300).Perform(); // Up 300px
// Scroll from elementnew Actions(driver) .ScrollFromOrigin( new WheelInputDevice.ScrollOrigin(footer, 0, 0), 0, 200 ) .Perform();Chaining Multiple Actions
Complex Action Chains
Selenium 3 & 4 Medium
WebElement source = driver.findElement(By.id("draggable"));WebElement target = driver.findElement(By.id("droppable"));
// Complex interaction chainActions actions = new Actions(driver);actions.moveToElement(source) .pause(Duration.ofMillis(200)) .click() .pause(Duration.ofMillis(100)) .clickAndHold() .moveToElement(target) .pause(Duration.ofMillis(200)) .release() .perform();
// Chain with keyboard modifieractions.keyDown(Keys.CONTROL) .click(driver.findElement(By.id("item1"))) .click(driver.findElement(By.id("item2"))) .click(driver.findElement(By.id("item3"))) .keyUp(Keys.CONTROL) .perform(); // Multi-select with Ctrl+Clicksource = driver.find_element(By.ID, "draggable")target = driver.find_element(By.ID, "droppable")
# Complex interaction chainactions = ActionChains(driver)actions.move_to_element(source) .pause(0.2) .click() .pause(0.1) .click_and_hold() .move_to_element(target) .pause(0.2) .release() .perform()
# Chain with keyboard modifieractions = ActionChains(driver)actions.key_down(Keys.CONTROL) .click(driver.find_element(By.ID, "item1")) .click(driver.find_element(By.ID, "item2")) .click(driver.find_element(By.ID, "item3")) .key_up(Keys.CONTROL) .perform() # Multi-select with Ctrl+Clickconst source = await driver.findElement(By.id('draggable'));const target = await driver.findElement(By.id('droppable'));
// Complex interaction chainawait driver.actions({ async: true }) .move({ origin: source }) .pause(200) .click() .pause(100) .press() .move({ origin: target }) .pause(200) .release() .perform();
// Chain with keyboard modifierconst item1 = await driver.findElement(By.id('item1'));const item2 = await driver.findElement(By.id('item2'));const item3 = await driver.findElement(By.id('item3'));
await driver.actions({ async: true }) .keyDown(Key.CONTROL) .click(item1) .click(item2) .click(item3) .keyUp(Key.CONTROL) .perform(); // Multi-select with Ctrl+ClickIWebElement source = driver.FindElement(By.Id("draggable"));IWebElement target = driver.FindElement(By.Id("droppable"));
// Complex interaction chainnew Actions(driver) .MoveToElement(source) .Pause(TimeSpan.FromMilliseconds(200)) .Click() .Pause(TimeSpan.FromMilliseconds(100)) .ClickAndHold() .MoveToElement(target) .Pause(TimeSpan.FromMilliseconds(200)) .Release() .Perform();
// Chain with keyboard modifiernew Actions(driver) .KeyDown(Keys.Control) .Click(driver.FindElement(By.Id("item1"))) .Click(driver.FindElement(By.Id("item2"))) .Click(driver.FindElement(By.Id("item3"))) .KeyUp(Keys.Control) .Perform(); // Multi-select with Ctrl+ClickBest Practices
- Use explicit waits after hover actions for menus to appear
- Add pauses when elements have animations
- Reset action chains between different interactions
- Test on different browsers - mouse behavior can vary
- Prefer element-based moves over coordinate-based when possible
Next Steps
- Drag and Drop - Dedicated drag operations
- Keyboard Actions - Combine with keyboard
- Explicit Waits - Wait for mouse effects