Actions API

Avanzado
Selenium
Selenium
Actualizado: 05/09/2025

¡Desbloquea el curso de Selenium completo!

IA
Ejercicios
Certificado
Entrar

Mira la lección en vídeo

Accede al vídeo completo de esta lección y a más contenido exclusivo con el Plan Plus.

Desbloquear Plan Plus

Actions API

La Actions API de Selenium representa el núcleo para ejecutar interacciones complejas con elementos web que van más allá de las operaciones básicas como click() y sendKeys(). Esta API permite simular comportamientos de usuario avanzados que requieren una secuencia de acciones coordinadas, como combinaciones de teclas, movimientos de ratón precisos, o interacciones que involucran múltiples elementos simultáneamente.

La clase Actions funciona como un constructor de secuencias que permite encadenar múltiples operaciones antes de ejecutarlas. Este enfoque resulta especialmente útil cuando necesitamos simular interacciones de usuario que requieren precisión temporal o coordinación entre diferentes tipos de entrada.

import org.openqa.selenium.interactions.Actions;

@Test
void inicializarActions() {
    Actions actions = new Actions(driver);
    // Las acciones se construyen pero no se ejecutan hasta llamar perform()
}

El patrón builder en Actions

La arquitectura de Actions sigue el patrón builder, permitiendo encadenar métodos de forma fluida. Cada método de acción devuelve la misma instancia de Actions, facilitando la construcción de secuencias complejas de interacciones:

@Test
void ejemploPatronBuilder() {
    WebElement elemento = driver.findElement(By.id("target"));
    
    Actions actions = new Actions(driver);
    actions.moveToElement(elemento)
           .pause(Duration.ofMillis(500))
           .click()
           .perform(); // Ejecuta toda la secuencia
}

El método perform() es fundamental en la API, ya que sin él, ninguna de las acciones definidas se ejecutará. Este diseño permite construir secuencias complejas de forma declarativa antes de su ejecución.

Gestión de timing y precisión

Una característica importante de la Actions API es su capacidad para controlar el timing entre acciones. El método pause() permite introducir demoras específicas dentro de una secuencia, lo cual resulta crucial para simular comportamientos de usuario realistas:

@Test
void controlTiming() {
    WebElement origen = driver.findElement(By.id("source"));
    WebElement destino = driver.findElement(By.id("target"));
    
    new Actions(driver)
        .moveToElement(origen)
        .pause(Duration.ofMillis(300))
        .clickAndHold()
        .pause(Duration.ofMillis(200))
        .moveToElement(destino)
        .release()
        .perform();
}

Coordinación de múltiples dispositivos de entrada

La Actions API permite coordinar simultáneamente acciones de ratón y teclado, algo que no es posible with los métodos básicos de WebElement. Esta capacidad es esencial para interacciones avanzadas que requieren modificadores de teclado junto con acciones de ratón:

@Test
void accionesCoordinadas() {
    WebElement elemento = driver.findElement(By.className("selectable"));
    
    new Actions(driver)
        .keyDown(Keys.CONTROL)
        .click(elemento)
        .keyUp(Keys.CONTROL)
        .perform();
}

Esta coordinación precisa entre dispositivos de entrada permite simular comportamientos de usuario sofisticados que serían imposibles de replicar usando únicamente los métodos estándar de WebElement.

Contexto de ejecución y ámbito

Es importante comprender que cada instancia de Actions mantiene su contexto de ejecución independiente. Las acciones se acumulan en una cola interna hasta que se invoca perform(), momento en el cual se ejecutan secuencialmente en el orden definido:

@Test
void contextosIndependientes() {
    Actions primeraSecuencia = new Actions(driver);
    Actions segundaSecuencia = new Actions(driver);
    
    // Cada Actions mantiene su propia secuencia
    primeraSecuencia.click(elemento1).pause(Duration.ofMillis(100));
    segundaSecuencia.doubleClick(elemento2);
    
    // Se ejecutan independientemente
    primeraSecuencia.perform();
    segundaSecuencia.perform();
}

Esta independencia de contexto permite crear múltiples secuencias de acciones reutilizables dentro del mismo test, facilitando la organización del código y la reutilización de patrones de interacción comunes.

Mouse actions y keyboard actions

Guarda tu progreso

Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.

Progreso guardado
Asistente IA
Ejercicios
Iniciar sesión gratis

Más de 25.000 desarrolladores ya confían en CertiDevs

Acciones de ratón fundamentales

Las acciones de ratón en la Actions API proporcionan un control granular sobre el comportamiento del cursor, permitiendo simular interacciones precisas que los usuarios realizan en aplicaciones web modernas.

El método moveToElement() constituye la base para muchas interacciones avanzadas, desplazando el cursor hacia un elemento específico sin realizar ninguna acción adicional. Esta funcionalidad es esencial para activar estados hover y preparar elementos para interacciones posteriores:

@Test
void movimientoBasicoRaton() {
    WebElement menu = driver.findElement(By.className("dropdown-trigger"));
    
    new Actions(driver)
        .moveToElement(menu)
        .perform();
    
    // El elemento ahora tiene el estado hover activo
    WebElement submenu = driver.findElement(By.className("dropdown-content"));
    assertTrue(submenu.isDisplayed());
}

Para interacciones que requieren doble clic, el método doubleClick() simula esta acción de forma nativa. Este comportamiento es común en interfaces que permiten editar contenido inline o activar funcionalidades específicas:

@Test
void dobleClicElemento() {
    WebElement textoEditable = driver.findElement(By.className("editable-text"));
    
    new Actions(driver)
        .doubleClick(textoEditable)
        .perform();
    
    // Verificar que el modo edición se activó
    WebElement campoInput = driver.findElement(By.tagName("input"));
    assertTrue(campoInput.isDisplayed());
}

Menús contextuales y clic derecho

El método contextClick() permite simular el clic derecho del ratón, activando menús contextuales que muchas aplicaciones web implementan para proporcionar opciones adicionales:

@Test
void menuContextual() {
    WebElement elemento = driver.findElement(By.id("context-target"));
    
    new Actions(driver)
        .contextClick(elemento)
        .perform();
    
    // Verificar que el menú contextual apareció
    WebElement menuContexto = driver.findElement(By.className("context-menu"));
    assertTrue(menuContexto.isDisplayed());
    
    // Seleccionar una opción del menú
    WebElement opcion = driver.findElement(By.xpath("//li[text()='Copiar']"));
    opcion.click();
}

Operaciones de arrastre con clickAndHold

El método clickAndHold() inicia una operación de arrastre manteniendo presionado el botón del ratón sobre un elemento. Esta acción se combina frecuentemente con moveToElement() y release() para crear interacciones de arrastre complejas:

@Test
void inicioArrastre() {
    WebElement elementoArrastrable = driver.findElement(By.className("draggable"));
    WebElement zonaDestino = driver.findElement(By.className("drop-zone"));
    
    new Actions(driver)
        .clickAndHold(elementoArrastrable)
        .moveToElement(zonaDestino)
        .release()
        .perform();
}

Acciones de teclado con modificadores

Las acciones de teclado permiten simular combinaciones de teclas complejas utilizando modificadores como Control, Shift y Alt. Los métodos keyDown() y keyUp() proporcionan control preciso sobre cuándo se presionan y sueltan las teclas modificadoras:

@Test
void combinacionesTeclado() {
    WebElement campoTexto = driver.findElement(By.id("texto-input"));
    campoTexto.click();
    campoTexto.sendKeys("Texto de ejemplo");
    
    // Seleccionar todo el texto con Ctrl+A
    new Actions(driver)
        .keyDown(Keys.CONTROL)
        .sendKeys("a")
        .keyUp(Keys.CONTROL)
        .perform();
    
    // Copiar el texto seleccionado
    new Actions(driver)
        .keyDown(Keys.CONTROL)
        .sendKeys("c")
        .keyUp(Keys.CONTROL)
        .perform();
}

Modificadores múltiples y secuencias complejas

La Actions API permite combinar múltiples modificadores simultáneamente, lo cual es útil para atajos de teclado avanzados que requieren varias teclas especiales:

@Test
void modificadoresMultiples() {
    WebElement editor = driver.findElement(By.className("code-editor"));
    editor.click();
    
    // Comentar línea con Ctrl+Shift+/
    new Actions(driver)
        .keyDown(Keys.CONTROL)
        .keyDown(Keys.SHIFT)
        .sendKeys("/")
        .keyUp(Keys.SHIFT)
        .keyUp(Keys.CONTROL)
        .perform();
}

Navegación con teclas especiales

Las teclas de navegación como las flechas direccionales, Tab, Enter y Escape se manejan através de la clase Keys, permitiendo simular navegación por teclado en interfaces complejas:

@Test
void navegacionTeclado() {
    WebElement primerElemento = driver.findElement(By.className("focusable"));
    primerElemento.click();
    
    // Navegar entre elementos con Tab
    new Actions(driver)
        .sendKeys(Keys.TAB)
        .sendKeys(Keys.TAB)
        .sendKeys(Keys.ENTER)
        .perform();
    
    // Navegar en menús con flechas
    new Actions(driver)
        .sendKeys(Keys.ARROW_DOWN)
        .sendKeys(Keys.ARROW_DOWN)
        .sendKeys(Keys.ENTER)
        .perform();
}

Casos de uso empresariales

En aplicaciones empresariales, estas acciones son fundamentales para automatizar workflows complejos. Por ejemplo, la gestión de selecciones múltiples en tablas de datos:

@Test
void seleccionMultipleTabla() {
    List<WebElement> filas = driver.findElements(By.cssSelector("table tr"));
    
    // Seleccionar primera fila
    new Actions(driver)
        .click(filas.get(1))
        .perform();
    
    // Añadir segunda fila a la selección con Ctrl+click
    new Actions(driver)
        .keyDown(Keys.CONTROL)
        .click(filas.get(3))
        .keyUp(Keys.CONTROL)
        .perform();
    
    // Extender selección con Shift+click
    new Actions(driver)
        .keyDown(Keys.SHIFT)
        .click(filas.get(5))
        .keyUp(Keys.SHIFT)
        .perform();
}

Combinación de acciones de ratón y teclado

La potencia real de la Actions API se manifiesta cuando combinamos acciones de ratón y teclado en secuencias coordinadas que replican comportamientos de usuario sofisticados:

@Test
void interaccionCompleja() {
    WebElement lienzo = driver.findElement(By.id("drawing-canvas"));
    
    // Dibujar manteniendo Shift para líneas rectas
    new Actions(driver)
        .moveToElement(lienzo, 100, 100)
        .keyDown(Keys.SHIFT)
        .clickAndHold()
        .moveByOffset(200, 0)
        .release()
        .keyUp(Keys.SHIFT)
        .perform();
}

Drag and drop y hover

Operaciones de drag and drop nativas

Las operaciones de arrastre y soltado representan una de las interacciones más complejas en aplicaciones web modernas. Selenium proporciona métodos específicos que simplifican estas operaciones, eliminando la necesidad de construir manualmente secuencias con clickAndHold(), moveToElement() y release().

El método dragAndDrop() ejecuta una operación completa de arrastre entre dos elementos en una sola llamada, manejando internamente toda la secuencia de acciones necesarias:

@Test
void dragAndDropBasico() {
    WebElement elementoOrigen = driver.findElement(By.id("draggable-item"));
    WebElement zonaDestino = driver.findElement(By.id("drop-target"));
    
    new Actions(driver)
        .dragAndDrop(elementoOrigen, zonaDestino)
        .perform();
    
    // Verificar que el elemento se movió correctamente
    assertEquals("drop-target", elementoOrigen.findElement(By.xpath("./..")).getAttribute("id"));
}

Arrastre con desplazamiento por píxeles

Para casos donde no existe un elemento de destino específico, dragAndDropBy() permite arrastrar un elemento desplazándolo por píxeles relativos a su posición actual. Esta funcionalidad es especialmente útil en editores gráficos, herramientas de diseño o interfaces de configuración visual:

@Test
void dragAndDropPorPixeles() {
    WebElement slider = driver.findElement(By.className("range-slider-handle"));
    
    // Mover el slider 150 píxeles hacia la derecha
    new Actions(driver)
        .dragAndDropBy(slider, 150, 0)
        .perform();
    
    // Verificar el nuevo valor del slider
    String valorActual = slider.getAttribute("aria-valuenow");
    assertTrue(Integer.parseInt(valorActual) > 50);
}

Drag and drop en listas reordenables

Una aplicación común del drag and drop es la reordenación de elementos en listas. Este patrón es frecuente en interfaces administrativas, paneles de control y aplicaciones de gestión de contenido:

@Test
void reordenarListaElementos() {
    List<WebElement> elementos = driver.findElements(By.className("sortable-item"));
    WebElement primerElemento = elementos.get(0);
    WebElement tercerElemento = elementos.get(2);
    
    // Mover el primer elemento a la tercera posición
    new Actions(driver)
        .dragAndDrop(primerElemento, tercerElemento)
        .perform();
    
    // Verificar el nuevo orden
    List<WebElement> elementosActualizados = driver.findElements(By.className("sortable-item"));
    assertNotEquals(primerElemento.getText(), elementosActualizados.get(0).getText());
}

Kanban boards y gestión de tareas

En aplicaciones empresariales tipo Kanban o gestores de proyectos, el drag and drop permite mover tareas entre diferentes estados o columnas:

@Test
void moverTareaKanban() {
    WebElement tarea = driver.findElement(By.xpath("//div[@data-task-id='TASK-123']"));
    WebElement columnaEnProceso = driver.findElement(By.className("column-in-progress"));
    
    // Mover tarea de "To Do" a "In Progress"
    new Actions(driver)
        .dragAndDrop(tarea, columnaEnProceso)
        .perform();
    
    // Verificar que la tarea cambió de estado
    WebElement tareaMovida = driver.findElement(By.xpath("//div[@data-task-id='TASK-123']"));
    assertEquals("in-progress", tareaMovida.findElement(By.xpath("./..")).getAttribute("data-status"));
}

Efectos hover avanzados y navegación por menús

Los efectos hover van más allá del simple posicionamiento del cursor. En aplicaciones complejas, el hover puede activar animaciones, cargar contenido dinámico o revelar opciones de navegación anidadas:

@Test
void navegacionMenuMultinivel() {
    WebElement menuPrincipal = driver.findElement(By.className("main-menu-item"));
    
    // Activar el primer nivel del menú
    new Actions(driver)
        .moveToElement(menuPrincipal)
        .perform();
    
    // Esperar a que aparezca el submenu
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));
    WebElement submenu = wait.until(ExpectedConditions.visibilityOfElementLocated(
        By.className("submenu-level-1")));
    
    // Navegar al segundo nivel
    WebElement itemSubmenu = submenu.findElement(By.className("submenu-item"));
    new Actions(driver)
        .moveToElement(itemSubmenu)
        .perform();
    
    // Verificar que el menú de tercer nivel apareció
    WebElement submenuNivel2 = wait.until(ExpectedConditions.visibilityOfElementLocated(
        By.className("submenu-level-2")));
    assertTrue(submenuNivel2.isDisplayed());
}

Tooltips y información contextual

El hover también activa tooltips informativos que proporcionan contexto adicional sobre elementos de la interfaz. Estos componentes son cruciales para la experiencia de usuario en aplicaciones complejas:

@Test
void verificarTooltipInformativo() {
    WebElement iconoAyuda = driver.findElement(By.className("help-icon"));
    
    new Actions(driver)
        .moveToElement(iconoAyuda)
        .perform();
    
    // Verificar que el tooltip apareció con el contenido esperado
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(2));
    WebElement tooltip = wait.until(ExpectedConditions.visibilityOfElementLocated(
        By.className("tooltip")));
    
    String textoTooltip = tooltip.getText();
    assertTrue(textoTooltip.contains("Esta función permite"));
}

Drag and drop con validación de zona válida

En interfaces sofisticadas, no todas las zonas permiten soltar elementos. Es importante validar que el drag and drop se realiza en áreas permitidas y manejar las restricciones correspondientes:

@Test
void dragAndDropConValidacion() {
    WebElement documento = driver.findElement(By.className("document-item"));
    WebElement carpetaValida = driver.findElement(By.cssSelector(".folder[data-accepts='documents']"));
    WebElement carpetaInvalida = driver.findElement(By.cssSelector(".folder[data-accepts='images']"));
    
    // Intentar arrastrar a zona inválida
    new Actions(driver)
        .dragAndDrop(documento, carpetaInvalida)
        .perform();
    
    // Verificar que el documento no se movió
    assertFalse(carpetaInvalida.findElements(By.className("document-item")).size() > 0);
    
    // Arrastrar a zona válida
    new Actions(driver)
        .dragAndDrop(documento, carpetaValida)
        .perform();
    
    // Verificar que el movimiento fue exitoso
    assertTrue(carpetaValida.findElements(By.className("document-item")).size() > 0);
}

Interacciones complejas con timing controlado

Algunas aplicaciones requieren timing específico durante las operaciones de drag and drop, especialmente cuando hay animaciones o efectos visuales que deben completarse:

@Test
void dragAndDropConTiming() {
    WebElement elementoComplejo = driver.findElement(By.className("animated-item"));
    WebElement zonaEspecial = driver.findElement(By.className("special-drop-zone"));
    
    new Actions(driver)
        .clickAndHold(elementoComplejo)
        .pause(Duration.ofMillis(500)) // Esperar animación de inicio
        .moveToElement(zonaEspecial)
        .pause(Duration.ofMillis(300)) // Permitir detección de zona válida
        .release()
        .perform();
    
    // Verificar el resultado después de las animaciones
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));
    wait.until(ExpectedConditions.attributeContains(elementoComplejo, "class", "dropped"));
}

Hover con efectos de carga dinámica

En aplicaciones modernas, el hover puede disparar cargas de contenido desde el servidor. Estos casos requieren esperas específicas para verificar que el contenido se cargó correctamente:

@Test
void hoverConCargaDinamica() {
    WebElement tarjetaUsuario = driver.findElement(By.className("user-card"));
    
    new Actions(driver)
        .moveToElement(tarjetaUsuario)
        .perform();
    
    // Esperar a que se cargue información adicional del usuario
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
    WebElement perfilCompleto = wait.until(ExpectedConditions.visibilityOfElementLocated(
        By.className("user-profile-expanded")));
    
    // Verificar que se cargaron datos específicos
    WebElement estadisticas = perfilCompleto.findElement(By.className("user-stats"));
    assertTrue(estadisticas.findElements(By.className("stat-item")).size() > 0);
}

Casos de uso en editores visuales

Los editores visuales representan uno de los contextos más exigentes para drag and drop, requiriendo precisión píxel por píxel y manejo de múltiples tipos de elementos:

@Test
void editorVisualDragAndDrop() {
    WebElement componenteTexto = driver.findElement(By.className("component-text"));
    WebElement lienzo = driver.findElement(By.id("design-canvas"));
    
    // Arrastrar componente al lienzo en posición específica
    new Actions(driver)
        .dragAndDropBy(componenteTexto, 250, 180)
        .perform();
    
    // Verificar que el componente se posicionó correctamente
    WebElement componenteEnLienzo = lienzo.findElement(By.className("component-text"));
    String posicionX = componenteEnLienzo.getCssValue("left");
    String posicionY = componenteEnLienzo.getCssValue("top");
    
    assertTrue(posicionX.contains("250"));
    assertTrue(posicionY.contains("180"));
}

Aprendizajes de esta lección de Selenium

  • Comprender el funcionamiento y arquitectura de la Actions API en Selenium.
  • Aprender a construir y ejecutar secuencias complejas de acciones con el patrón builder.
  • Controlar el timing y la precisión en interacciones avanzadas.
  • Dominar acciones de ratón y teclado, incluyendo combinaciones y modificadores.
  • Aplicar técnicas de drag and drop y efectos hover en escenarios reales y empresariales.

Completa este curso de Selenium y certifícate

Únete a nuestra plataforma de cursos de programación y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.

Asistente IA

Resuelve dudas al instante

Ejercicios

Practica con proyectos reales

Certificados

Valida tus conocimientos

Más de 25.000 desarrolladores ya se han certificado con CertiDevs

⭐⭐⭐⭐⭐
4.9/5 valoración