Keyboard actions
A representation of any key input device for interacting with a web page.
In addition to the high-level element interactions, the Actions API provides granular control over exactly what designated input devices can do. Selenium provides an interface for 3 kinds of input sources: a key input for keyboard devices, a pointer input for a mouse, pen or touch devices, and wheel inputs for scroll wheel devices (introduced in Selenium 4.2). Selenium allows you to construct individual action commands assigned to specific inputs and chain them together and call the associated perform method to execute them all at once.
In the move from the legacy JSON Wire Protocol to the new W3C WebDriver Protocol, the low level building blocks of actions became especially detailed. It is extremely powerful, but each input device has a number of ways to use it and if you need to manage more than one device, you are responsible for ensuring proper synchronization between them.
Thankfully, you likely do not need to learn how to use the low level commands directly, since almost everything you might want to do has been given a convenience method that combines the lower level commands for you. These are all documented in keyboard, mouse, pen, and wheel pages.
Pointer movements and Wheel scrolling allow the user to set a duration for the action, but sometimes you just need to wait a beat between actions for things to work correctly.
WebElement clickable = driver.findElement(By.id("clickable"));
new Actions(driver)
.moveToElement(clickable)
.pause(Duration.ofSeconds(1))
.clickAndHold()
.pause(Duration.ofSeconds(1))
.sendKeys("abc")
.perform();
package dev.selenium.actions_api;
import dev.selenium.BaseChromeTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.RemoteWebDriver;
import java.time.Duration;
public class ActionsTest extends BaseChromeTest {
@Test
public void pause() {
driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html");
long start = System.currentTimeMillis();
WebElement clickable = driver.findElement(By.id("clickable"));
new Actions(driver)
.moveToElement(clickable)
.pause(Duration.ofSeconds(1))
.clickAndHold()
.pause(Duration.ofSeconds(1))
.sendKeys("abc")
.perform();
long duration = System.currentTimeMillis() - start;
Assertions.assertTrue(duration > 2000);
Assertions.assertTrue(duration < 3000);
}
@Test
public void releasesAll() {
driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html");
WebElement clickable = driver.findElement(By.id("clickable"));
Actions actions = new Actions(driver);
actions.clickAndHold(clickable)
.keyDown(Keys.SHIFT)
.sendKeys("a")
.perform();
((RemoteWebDriver) driver).resetInputState();
actions.sendKeys("a").perform();
Assertions.assertEquals("A", String.valueOf(clickable.getAttribute("value").charAt(0)));
Assertions.assertEquals("a", String.valueOf(clickable.getAttribute("value").charAt(1)));
}
}
clickable = driver.find_element(By.ID, "clickable")
ActionChains(driver)\
.move_to_element(clickable)\
.pause(1)\
.click_and_hold()\
.pause(1)\
.send_keys("abc")\
.perform()
from time import time
from selenium.webdriver import Keys, ActionChains
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.by import By
def test_pauses(driver):
driver.get('https://selenium.dev/selenium/web/mouse_interaction.html')
start = time()
clickable = driver.find_element(By.ID, "clickable")
ActionChains(driver)\
.move_to_element(clickable)\
.pause(1)\
.click_and_hold()\
.pause(1)\
.send_keys("abc")\
.perform()
duration = time() - start
assert duration > 2
assert duration < 3
def test_releases_all(driver):
driver.get('https://selenium.dev/selenium/web/mouse_interaction.html')
clickable = driver.find_element(By.ID, "clickable")
ActionChains(driver)\
.click_and_hold(clickable)\
.key_down(Keys.SHIFT)\
.key_down("a")\
.perform()
ActionBuilder(driver).clear_actions()
ActionChains(driver).key_down('a').perform()
assert clickable.get_attribute('value')[0] == "A"
assert clickable.get_attribute('value')[1] == "a"
IWebElement clickable = driver.FindElement(By.Id("clickable"));
new Actions(driver)
.MoveToElement(clickable)
.Pause(TimeSpan.FromSeconds(1))
.ClickAndHold()
.Pause(TimeSpan.FromSeconds(1))
.SendKeys("abc")
.Perform();
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Interactions;
namespace SeleniumDocs.ActionsAPI
{
[TestClass]
public class ActionsTest : BaseChromeTest
{
[TestMethod]
public void Pause()
{
driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html";
DateTime start = DateTime.Now;
IWebElement clickable = driver.FindElement(By.Id("clickable"));
new Actions(driver)
.MoveToElement(clickable)
.Pause(TimeSpan.FromSeconds(1))
.ClickAndHold()
.Pause(TimeSpan.FromSeconds(1))
.SendKeys("abc")
.Perform();
TimeSpan duration = DateTime.Now - start;
Assert.IsTrue(duration > TimeSpan.FromSeconds(2));
Assert.IsTrue(duration < TimeSpan.FromSeconds(3));
}
[TestMethod]
public void ReleaseAll()
{
driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html";
IWebElement clickable = driver.FindElement(By.Id("clickable"));
var actions = new Actions(driver);
actions.ClickAndHold(clickable)
.KeyDown(Keys.Shift)
.SendKeys("a")
.Perform();
((WebDriver)driver).ResetInputState();
actions.SendKeys("a").Perform();
var value = clickable.GetAttribute("value");
Assert.AreEqual("A", value[..1]);
Assert.AreEqual("a", value.Substring(1, 1));
}
}
}
clickable = driver.find_element(id: 'clickable')
driver.action
.move_to(clickable)
.pause(duration: 1)
.click_and_hold
.pause(duration: 1)
.send_keys('abc')
.perform
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Actions' do
let(:driver) { start_session }
it 'pauses' do
driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html'
start = Time.now
clickable = driver.find_element(id: 'clickable')
driver.action
.move_to(clickable)
.pause(duration: 1)
.click_and_hold
.pause(duration: 1)
.send_keys('abc')
.perform
duration = Time.now - start
expect(duration).to be > 2
expect(duration).to be < 3
end
it 'releases all' do
driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html'
clickable = driver.find_element(id: 'clickable')
action = driver.action
.click_and_hold(clickable)
.key_down(:shift)
.key_down('a')
action.perform
driver.action.release_actions
action.key_down('a').perform
expect(clickable.attribute('value')[0]).to eq 'A'
expect(clickable.attribute('value')[-1]).to eq 'a'
end
end
const clickable = await driver.findElement(By.id('clickable'))
await driver.actions()
.move({ origin: clickable })
.pause(1000)
.press()
.pause(1000)
.sendKeys('abc')
.perform()
const { By, Key, Browser, Builder} = require('selenium-webdriver')
const assert = require('assert')
describe('Actions API - Pause and Release All Actions', function() {
let driver
before(async function() {
driver = await new Builder().forBrowser('chrome').build();
})
after(async () => await driver.quit())
it('Pause', async function() {
await driver.get('https://selenium.dev/selenium/web/mouse_interaction.html')
const start = Date.now()
const clickable = await driver.findElement(By.id('clickable'))
await driver.actions()
.move({ origin: clickable })
.pause(1000)
.press()
.pause(1000)
.sendKeys('abc')
.perform()
const end = Date.now() - start
assert.ok(end > 2000)
assert.ok(end < 4000)
})
it('Clear', async function() {
await driver.get('https://selenium.dev/selenium/web/mouse_interaction.html')
const clickable = driver.findElement(By.id('clickable'))
await driver.actions()
.click(clickable)
.keyDown(Key.SHIFT)
.sendKeys('a')
.perform()
await driver.actions().clear()
await driver.actions().sendKeys('a').perform()
const value = await clickable.getAttribute('value')
assert.deepStrictEqual('A', value.substring(0, 1))
assert.deepStrictEqual('a', value.substring(1, 2))
})
})
val clickable = driver.findElement(By.id("clickable"))
Actions(driver)
.moveToElement(clickable)
.pause(Duration.ofSeconds(1))
.clickAndHold()
.pause(Duration.ofSeconds(1))
.sendKeys("abc")
.perform()
package dev.selenium.actions_api
import dev.selenium.BaseTest
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.openqa.selenium.By
import org.openqa.selenium.Keys
import org.openqa.selenium.WebElement
import org.openqa.selenium.interactions.Actions
import org.openqa.selenium.remote.RemoteWebDriver
import java.time.Duration
class ActionsTest : BaseTest() {
@Test
fun pause() {
driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html")
val start = System.currentTimeMillis()
val clickable = driver.findElement(By.id("clickable"))
Actions(driver)
.moveToElement(clickable)
.pause(Duration.ofSeconds(1))
.clickAndHold()
.pause(Duration.ofSeconds(1))
.sendKeys("abc")
.perform()
val duration = System.currentTimeMillis() - start
Assertions.assertTrue(duration > 2000)
Assertions.assertTrue(duration < 4000)
}
@Test
fun releasesAll() {
driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html")
val clickable = driver.findElement(By.id("clickable"))
val actions = Actions(driver)
actions.clickAndHold(clickable)
.keyDown(Keys.SHIFT)
.sendKeys("a")
.perform()
(driver as RemoteWebDriver).resetInputState()
actions.sendKeys("a").perform()
Assertions.assertEquals("A", clickable.getAttribute("value")!!.get(0).toString())
Assertions.assertEquals("a", clickable.getAttribute("value")!!.get(1).toString())
}
}
An important thing to note is that the driver remembers the state of all the input items throughout a session. Even if you create a new instance of an actions class, the depressed keys and the location of the pointer will be in whatever state a previously performed action left them.
There is a special method to release all currently depressed keys and pointer buttons. This method is implemented differently in each of the languages because it does not get executed with the perform method.
((RemoteWebDriver) driver).resetInputState();
package dev.selenium.actions_api;
import dev.selenium.BaseChromeTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.RemoteWebDriver;
import java.time.Duration;
public class ActionsTest extends BaseChromeTest {
@Test
public void pause() {
driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html");
long start = System.currentTimeMillis();
WebElement clickable = driver.findElement(By.id("clickable"));
new Actions(driver)
.moveToElement(clickable)
.pause(Duration.ofSeconds(1))
.clickAndHold()
.pause(Duration.ofSeconds(1))
.sendKeys("abc")
.perform();
long duration = System.currentTimeMillis() - start;
Assertions.assertTrue(duration > 2000);
Assertions.assertTrue(duration < 3000);
}
@Test
public void releasesAll() {
driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html");
WebElement clickable = driver.findElement(By.id("clickable"));
Actions actions = new Actions(driver);
actions.clickAndHold(clickable)
.keyDown(Keys.SHIFT)
.sendKeys("a")
.perform();
((RemoteWebDriver) driver).resetInputState();
actions.sendKeys("a").perform();
Assertions.assertEquals("A", String.valueOf(clickable.getAttribute("value").charAt(0)));
Assertions.assertEquals("a", String.valueOf(clickable.getAttribute("value").charAt(1)));
}
}
ActionBuilder(driver).clear_actions()
from time import time
from selenium.webdriver import Keys, ActionChains
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.by import By
def test_pauses(driver):
driver.get('https://selenium.dev/selenium/web/mouse_interaction.html')
start = time()
clickable = driver.find_element(By.ID, "clickable")
ActionChains(driver)\
.move_to_element(clickable)\
.pause(1)\
.click_and_hold()\
.pause(1)\
.send_keys("abc")\
.perform()
duration = time() - start
assert duration > 2
assert duration < 3
def test_releases_all(driver):
driver.get('https://selenium.dev/selenium/web/mouse_interaction.html')
clickable = driver.find_element(By.ID, "clickable")
ActionChains(driver)\
.click_and_hold(clickable)\
.key_down(Keys.SHIFT)\
.key_down("a")\
.perform()
ActionBuilder(driver).clear_actions()
ActionChains(driver).key_down('a').perform()
assert clickable.get_attribute('value')[0] == "A"
assert clickable.get_attribute('value')[1] == "a"
((WebDriver)driver).ResetInputState();
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Interactions;
namespace SeleniumDocs.ActionsAPI
{
[TestClass]
public class ActionsTest : BaseChromeTest
{
[TestMethod]
public void Pause()
{
driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html";
DateTime start = DateTime.Now;
IWebElement clickable = driver.FindElement(By.Id("clickable"));
new Actions(driver)
.MoveToElement(clickable)
.Pause(TimeSpan.FromSeconds(1))
.ClickAndHold()
.Pause(TimeSpan.FromSeconds(1))
.SendKeys("abc")
.Perform();
TimeSpan duration = DateTime.Now - start;
Assert.IsTrue(duration > TimeSpan.FromSeconds(2));
Assert.IsTrue(duration < TimeSpan.FromSeconds(3));
}
[TestMethod]
public void ReleaseAll()
{
driver.Url = "https://selenium.dev/selenium/web/mouse_interaction.html";
IWebElement clickable = driver.FindElement(By.Id("clickable"));
var actions = new Actions(driver);
actions.ClickAndHold(clickable)
.KeyDown(Keys.Shift)
.SendKeys("a")
.Perform();
((WebDriver)driver).ResetInputState();
actions.SendKeys("a").Perform();
var value = clickable.GetAttribute("value");
Assert.AreEqual("A", value[..1]);
Assert.AreEqual("a", value.Substring(1, 1));
}
}
}
driver.action.release_actions
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Actions' do
let(:driver) { start_session }
it 'pauses' do
driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html'
start = Time.now
clickable = driver.find_element(id: 'clickable')
driver.action
.move_to(clickable)
.pause(duration: 1)
.click_and_hold
.pause(duration: 1)
.send_keys('abc')
.perform
duration = Time.now - start
expect(duration).to be > 2
expect(duration).to be < 3
end
it 'releases all' do
driver.get 'https://www.selenium.dev/selenium/web/mouse_interaction.html'
clickable = driver.find_element(id: 'clickable')
action = driver.action
.click_and_hold(clickable)
.key_down(:shift)
.key_down('a')
action.perform
driver.action.release_actions
action.key_down('a').perform
expect(clickable.attribute('value')[0]).to eq 'A'
expect(clickable.attribute('value')[-1]).to eq 'a'
end
end
await driver.actions().clear()
const { By, Key, Browser, Builder} = require('selenium-webdriver')
const assert = require('assert')
describe('Actions API - Pause and Release All Actions', function() {
let driver
before(async function() {
driver = await new Builder().forBrowser('chrome').build();
})
after(async () => await driver.quit())
it('Pause', async function() {
await driver.get('https://selenium.dev/selenium/web/mouse_interaction.html')
const start = Date.now()
const clickable = await driver.findElement(By.id('clickable'))
await driver.actions()
.move({ origin: clickable })
.pause(1000)
.press()
.pause(1000)
.sendKeys('abc')
.perform()
const end = Date.now() - start
assert.ok(end > 2000)
assert.ok(end < 4000)
})
it('Clear', async function() {
await driver.get('https://selenium.dev/selenium/web/mouse_interaction.html')
const clickable = driver.findElement(By.id('clickable'))
await driver.actions()
.click(clickable)
.keyDown(Key.SHIFT)
.sendKeys('a')
.perform()
await driver.actions().clear()
await driver.actions().sendKeys('a').perform()
const value = await clickable.getAttribute('value')
assert.deepStrictEqual('A', value.substring(0, 1))
assert.deepStrictEqual('a', value.substring(1, 2))
})
})
(driver as RemoteWebDriver).resetInputState()
package dev.selenium.actions_api
import dev.selenium.BaseTest
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.openqa.selenium.By
import org.openqa.selenium.Keys
import org.openqa.selenium.WebElement
import org.openqa.selenium.interactions.Actions
import org.openqa.selenium.remote.RemoteWebDriver
import java.time.Duration
class ActionsTest : BaseTest() {
@Test
fun pause() {
driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html")
val start = System.currentTimeMillis()
val clickable = driver.findElement(By.id("clickable"))
Actions(driver)
.moveToElement(clickable)
.pause(Duration.ofSeconds(1))
.clickAndHold()
.pause(Duration.ofSeconds(1))
.sendKeys("abc")
.perform()
val duration = System.currentTimeMillis() - start
Assertions.assertTrue(duration > 2000)
Assertions.assertTrue(duration < 4000)
}
@Test
fun releasesAll() {
driver.get("https://www.selenium.dev/selenium/web/mouse_interaction.html")
val clickable = driver.findElement(By.id("clickable"))
val actions = Actions(driver)
actions.clickAndHold(clickable)
.keyDown(Keys.SHIFT)
.sendKeys("a")
.perform()
(driver as RemoteWebDriver).resetInputState()
actions.sendKeys("a").perform()
Assertions.assertEquals("A", clickable.getAttribute("value")!!.get(0).toString())
Assertions.assertEquals("a", clickable.getAttribute("value")!!.get(1).toString())
}
}
A representation of any key input device for interacting with a web page.
A representation of any pointer device for interacting with a web page.
A representation of a pen stylus kind of pointer input for interacting with a web page.
A representation of a scroll wheel input device for interacting with a web page.
Learn more or view the full list of sponsors.