Interacción con formularios

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

Trabajar con inputs, textareas y checkboxes

Los formularios web constituyen uno de los elementos más frecuentes en las aplicaciones modernas, y su correcta automatización resulta fundamental para garantizar la calidad del software. Selenium WebDriver proporciona métodos específicos para interactuar con diferentes tipos de campos de entrada, desde inputs básicos hasta elementos más complejos como checkboxes y radio buttons.

La interacción con campos de texto sigue patrones consistentes que permiten simular el comportamiento real del usuario. Los métodos principales incluyen sendKeys() para introducir texto, clear() para limpiar el contenido existente, y getText() o getAttribute("value") para recuperar valores.

Interacción con campos de entrada de texto

Los campos de entrada (<input>) representan la forma más común de captura de datos en formularios web. Selenium maneja diferentes tipos de input de manera uniforme, adaptándose automáticamente a las características específicas de cada tipo.

@Test
void testInputFields() {
    // Input de texto básico
    WebElement nameField = driver.findElement(By.id("name"));
    nameField.clear();
    nameField.sendKeys("Juan Pérez");
    
    // Input de email con validación HTML5
    WebElement emailField = driver.findElement(By.name("email"));
    emailField.sendKeys("juan.perez@empresa.com");
    
    // Input de contraseña
    WebElement passwordField = driver.findElement(By.id("password"));
    passwordField.sendKeys("MiContraseña123!");
}

Los campos numéricos requieren consideraciones especiales, especialmente cuando el navegador aplica validaciones automáticas. Es recomendable enviar los valores como cadenas de texto para mantener compatibilidad entre diferentes navegadores.

@Test
void testNumericInputs() {
    WebElement ageField = driver.findElement(By.id("age"));
    ageField.clear();
    ageField.sendKeys("25");
    
    // Para campos con decimales
    WebElement salaryField = driver.findElement(By.name("salary"));
    salaryField.sendKeys("45000.50");
    
    // Verificar que el valor se ha establecido correctamente
    String enteredValue = ageField.getAttribute("value");
    assertEquals("25", enteredValue);
}

Los campos de fecha presentan variabilidad según el navegador y la configuración regional. La aproximación más robusta consiste en utilizar el formato ISO (YYYY-MM-DD) y verificar que el valor se ha establecido correctamente.

@Test
void testDateInputs() {
    WebElement birthDateField = driver.findElement(By.id("birthdate"));
    
    // Formato ISO para máxima compatibilidad
    birthDateField.sendKeys("1990-05-15");
    
    // Alternativamente, para campos que no soportan type="date"
    WebElement customDateField = driver.findElement(By.className("date-picker"));
    customDateField.clear();
    customDateField.sendKeys("15/05/1990");
}

Manejo de áreas de texto

Las áreas de texto (<textarea>) permiten la entrada de contenido multilínea y requieren técnicas específicas para manejar saltos de línea y formato. El método sendKeys() acepta caracteres especiales como \n para representar saltos de línea.

@Test
void testTextareaHandling() {
    WebElement commentArea = driver.findElement(By.id("comments"));
    
    String multilineText = """
        Este es un comentario de prueba
        que abarca múltiples líneas
        para verificar el comportamiento del textarea.
        """;
    
    commentArea.clear();
    commentArea.sendKeys(multilineText);
    
    // Verificar que el contenido se ha establecido
    String actualContent = commentArea.getAttribute("value");
    assertTrue(actualContent.contains("múltiples líneas"));
}

Para contenido extenso, es útil simular el comportamiento real del usuario combinando diferentes métodos de entrada. Esto incluye el uso de teclas especiales como Keys.TAB para navegación entre campos.

@Test
void testAdvancedTextareaInteraction() {
    WebElement descriptionArea = driver.findElement(By.name("description"));
    
    // Simular escritura gradual con teclas especiales
    descriptionArea.sendKeys("Descripción del producto:");
    descriptionArea.sendKeys(Keys.ENTER, Keys.ENTER);
    descriptionArea.sendKeys("- Característica 1");
    descriptionArea.sendKeys(Keys.ENTER);
    descriptionArea.sendKeys("- Característica 2");
    
    // Seleccionar todo el texto y reemplazarlo
    descriptionArea.sendKeys(Keys.CONTROL + "a");
    descriptionArea.sendKeys("Nueva descripción completa");
}

Interacción con checkboxes y radio buttons

Los checkboxes representan opciones binarias que pueden estar seleccionadas o no. El método click() alterna su estado, mientras que isSelected() permite verificar el estado actual. Es fundamental comprobar el estado antes de hacer clic para evitar comportamientos inesperados.

@Test
void testCheckboxInteraction() {
    WebElement termsCheckbox = driver.findElement(By.id("terms"));
    WebElement newsletterCheckbox = driver.findElement(By.name("newsletter"));
    
    // Verificar estado inicial
    assertFalse(termsCheckbox.isSelected());
    
    // Seleccionar checkbox si no está marcado
    if (!termsCheckbox.isSelected()) {
        termsCheckbox.click();
    }
    
    // Verificar que se ha seleccionado
    assertTrue(termsCheckbox.isSelected());
    
    // Manejar checkbox opcional
    if (!newsletterCheckbox.isSelected()) {
        newsletterCheckbox.click();
    }
}

Los radio buttons funcionan en grupos donde solo una opción puede estar seleccionada simultáneamente. La estrategia consiste en localizar el grupo completo y seleccionar la opción deseada verificando que las demás se deseleccionen automáticamente.

@Test
void testRadioButtonGroups() {
    // Localizar grupo de radio buttons por name
    List<WebElement> genderOptions = driver.findElements(By.name("gender"));
    
    // Seleccionar opción específica por valor
    genderOptions.stream()
        .filter(option -> "female".equals(option.getAttribute("value")))
        .findFirst()
        .ifPresent(WebElement::click);
    
    // Verificar selección
    WebElement selectedOption = genderOptions.stream()
        .filter(WebElement::isSelected)
        .findFirst()
        .orElseThrow();
    
    assertEquals("female", selectedOption.getAttribute("value"));
}

Para formularios complejos con múltiples grupos de radio buttons, es recomendable crear métodos auxiliares que encapsulen la lógica de selección y verificación.

@Test
void testMultipleRadioGroups() {
    // Grupo de experiencia
    selectRadioOption("experience", "senior");
    
    // Grupo de modalidad de trabajo
    selectRadioOption("work_mode", "remote");
    
    // Verificar selecciones
    assertTrue(isRadioSelected("experience", "senior"));
    assertTrue(isRadioSelected("work_mode", "remote"));
}

private void selectRadioOption(String groupName, String value) {
    driver.findElements(By.name(groupName)).stream()
        .filter(option -> value.equals(option.getAttribute("value")))
        .findFirst()
        .ifPresent(WebElement::click);
}

private boolean isRadioSelected(String groupName, String value) {
    return driver.findElements(By.name(groupName)).stream()
        .filter(option -> value.equals(option.getAttribute("value")))
        .findFirst()
        .map(WebElement::isSelected)
        .orElse(false);
}

La verificación de estado resulta crucial para asegurar la consistencia de los datos. Los checkboxes y radio buttons pueden cambiar su estado mediante JavaScript, por lo que es importante validar el estado después de cada interacción.

@Test
void testStateVerification() {
    WebElement agreeCheckbox = driver.findElement(By.id("agree"));
    WebElement disagreeCheckbox = driver.findElement(By.id("disagree"));
    
    // Estado inicial
    assertFalse(agreeCheckbox.isSelected());
    assertFalse(disagreeCheckbox.isSelected());
    
    // Seleccionar agree
    agreeCheckbox.click();
    
    // Verificar estados mutuamente excluyentes
    assertTrue(agreeCheckbox.isSelected());
    assertFalse(disagreeCheckbox.isSelected());
    
    // Cambiar selección
    disagreeCheckbox.click();
    
    // Verificar nuevo estado
    assertFalse(agreeCheckbox.isSelected());
    assertTrue(disagreeCheckbox.isSelected());
}

Manejo de dropdowns y Select

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

Los elementos dropdown (<select>) representan uno de los componentes más versátiles en formularios web, permitiendo a los usuarios elegir entre múltiples opciones de manera organizada. Selenium WebDriver proporciona la clase Select especializada que encapsula toda la funcionalidad necesaria para interactuar con estos elementos de forma robusta y eficiente.

La clase Select de Selenium

La clase Select actúa como un wrapper que simplifica significativamente la interacción con elementos <select>. Esta clase proporciona métodos específicos para seleccionar opciones por diferentes criterios y obtener información sobre el estado actual del dropdown.

@Test
void testBasicSelectUsage() {
    WebElement countryDropdown = driver.findElement(By.id("country"));
    Select countrySelect = new Select(countryDropdown);
    
    // Verificar que es un dropdown válido
    assertTrue(countrySelect.isMultiple() == false);
    
    // Seleccionar por texto visible
    countrySelect.selectByVisibleText("España");
    
    // Verificar selección actual
    WebElement selectedOption = countrySelect.getFirstSelectedOption();
    assertEquals("España", selectedOption.getText());
}

Métodos de selección

La clase Select ofrece tres métodos principales para seleccionar opciones, cada uno optimizado para diferentes escenarios de uso. La elección del método apropiado depende de la información disponible y la estabilidad de los datos.

1 - Selección por texto visible:

@Test
void testSelectByVisibleText() {
    Select departmentSelect = new Select(driver.findElement(By.name("department")));
    
    // Selección exacta por texto
    departmentSelect.selectByVisibleText("Recursos Humanos");
    
    // Verificar que la opción correcta está seleccionada
    String selectedText = departmentSelect.getFirstSelectedOption().getText();
    assertEquals("Recursos Humanos", selectedText);
}

2 - Selección por valor del atributo:

@Test
void testSelectByValue() {
    Select prioritySelect = new Select(driver.findElement(By.id("priority")));
    
    // Seleccionar por valor del atributo value
    prioritySelect.selectByValue("high");
    
    // Verificar usando el atributo value
    String selectedValue = prioritySelect.getFirstSelectedOption().getAttribute("value");
    assertEquals("high", selectedValue);
}

3 - Selección por índice:

@Test
void testSelectByIndex() {
    Select monthSelect = new Select(driver.findElement(By.id("birth_month")));
    
    // Seleccionar el tercer elemento (índice 2)
    monthSelect.selectByIndex(2);
    
    // Verificar que el índice correcto está seleccionado
    List<WebElement> allOptions = monthSelect.getOptions();
    WebElement selectedOption = monthSelect.getFirstSelectedOption();
    
    assertEquals(allOptions.get(2).getText(), selectedOption.getText());
}

Trabajar con opciones múltiples

Los elementos select múltiples permiten seleccionar varias opciones simultáneamente. La clase Select proporciona métodos específicos para manejar estas selecciones múltiples, incluyendo la capacidad de deseleccionar opciones específicas o todas las opciones.

@Test
void testMultipleSelectHandling() {
    Select skillsSelect = new Select(driver.findElement(By.id("skills")));
    
    // Verificar que soporta selección múltiple
    assertTrue(skillsSelect.isMultiple());
    
    // Seleccionar múltiples opciones
    skillsSelect.selectByVisibleText("Java");
    skillsSelect.selectByVisibleText("Python");
    skillsSelect.selectByValue("javascript");
    
    // Obtener todas las opciones seleccionadas
    List<WebElement> selectedOptions = skillsSelect.getAllSelectedOptions();
    assertEquals(3, selectedOptions.size());
    
    // Verificar opciones específicas
    List<String> selectedTexts = selectedOptions.stream()
        .map(WebElement::getText)
        .toList();
    
    assertTrue(selectedTexts.contains("Java"));
    assertTrue(selectedTexts.contains("Python"));
}

Métodos de deselección

Para elementos de selección múltiple, la clase Select proporciona métodos de deselección que permiten quitar opciones específicas o limpiar toda la selección. Estos métodos son especialmente útiles en formularios dinámicos donde las selecciones pueden cambiar durante la interacción.

@Test
void testDeselectMethods() {
    Select categoriesSelect = new Select(driver.findElement(By.name("categories")));
    
    // Seleccionar varias opciones inicialmente
    categoriesSelect.selectByVisibleText("Tecnología");
    categoriesSelect.selectByVisibleText("Ciencia");
    categoriesSelect.selectByVisibleText("Deportes");
    
    // Deseleccionar una opción específica por texto
    categoriesSelect.deselectByVisibleText("Deportes");
    
    // Deseleccionar por valor
    categoriesSelect.deselectByValue("science");
    
    // Verificar que solo queda una selección
    List<WebElement> remainingSelected = categoriesSelect.getAllSelectedOptions();
    assertEquals(1, remainingSelected.size());
    assertEquals("Tecnología", remainingSelected.get(0).getText());
    
    // Deseleccionar todas las opciones
    categoriesSelect.deselectAll();
    assertTrue(categoriesSelect.getAllSelectedOptions().isEmpty());
}

Obtención de información del dropdown

La clase Select permite extraer información completa sobre el estado y las opciones disponibles en un dropdown. Esta capacidad resulta fundamental para validaciones y verificaciones durante las pruebas automatizadas.

@Test
void testDropdownInformation() {
    Select statusSelect = new Select(driver.findElement(By.id("status")));
    
    // Obtener todas las opciones disponibles
    List<WebElement> allOptions = statusSelect.getOptions();
    
    // Verificar número total de opciones
    assertTrue(allOptions.size() > 0);
    
    // Extraer textos de todas las opciones
    List<String> optionTexts = allOptions.stream()
        .map(WebElement::getText)
        .filter(text -> !text.isEmpty())
        .toList();
    
    // Verificar que contiene opciones esperadas
    assertTrue(optionTexts.contains("Activo"));
    assertTrue(optionTexts.contains("Inactivo"));
    
    // Obtener valores de los atributos
    List<String> optionValues = allOptions.stream()
        .map(option -> option.getAttribute("value"))
        .filter(value -> value != null && !value.isEmpty())
        .toList();
    
    assertFalse(optionValues.isEmpty());
}

Manejo de dropdowns dinámicos

Los dropdowns dinámicos que cargan opciones mediante JavaScript requieren técnicas específicas para asegurar que las opciones estén disponibles antes de intentar seleccionarlas. La combinación de esperas explícitas con la clase Select proporciona una solución robusta.

@Test
void testDynamicDropdown() {
    // Trigger que carga opciones dinámicamente
    driver.findElement(By.id("load-cities")).click();
    
    // Esperar a que el dropdown tenga opciones
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    
    WebElement cityDropdown = wait.until(driver -> {
        WebElement dropdown = driver.findElement(By.id("city"));
        Select select = new Select(dropdown);
        return select.getOptions().size() > 1 ? dropdown : null;
    });
    
    Select citySelect = new Select(cityDropdown);
    
    // Verificar que las opciones se han cargado
    List<WebElement> options = citySelect.getOptions();
    assertTrue(options.size() > 1); // Más que solo la opción por defecto
    
    // Seleccionar una ciudad específica
    citySelect.selectByVisibleText("Madrid");
    
    assertEquals("Madrid", citySelect.getFirstSelectedOption().getText());
}

Validación y manejo de errores

La validación robusta de dropdowns incluye verificar que las opciones existen antes de intentar seleccionarlas, manejar casos donde las opciones pueden no estar disponibles, y proporcionar mensajes de error informativos.

@Test
void testDropdownValidation() {
    Select regionSelect = new Select(driver.findElement(By.name("region")));
    
    // Verificar que una opción específica existe antes de seleccionarla
    boolean optionExists = regionSelect.getOptions().stream()
        .anyMatch(option -> "Andalucía".equals(option.getText()));
    
    if (optionExists) {
        regionSelect.selectByVisibleText("Andalucía");
        assertEquals("Andalucía", regionSelect.getFirstSelectedOption().getText());
    } else {
        fail("La opción 'Andalucía' no está disponible en el dropdown");
    }
}

@Test
void testSafeDropdownSelection() {
    Select languageSelect = new Select(driver.findElement(By.id("language")));
    
    // Método seguro para seleccionar con fallback
    String[] preferredLanguages = {"Español", "Spanish", "ES"};
    
    boolean selected = Arrays.stream(preferredLanguages)
        .anyMatch(lang -> {
            try {
                languageSelect.selectByVisibleText(lang);
                return true;
            } catch (NoSuchElementException e) {
                return false;
            }
        });
    
    assertTrue(selected, "No se pudo seleccionar ningún idioma de las opciones preferidas");
}

Dropdowns personalizados y no nativos

Muchas aplicaciones modernas utilizan dropdowns personalizados construidos con divs y JavaScript en lugar de elementos <select> nativos. Para estos casos, es necesario utilizar métodos de interacción estándar de WebDriver sin la clase Select.

@Test
void testCustomDropdown() {
    // Abrir dropdown personalizado
    WebElement customDropdown = driver.findElement(By.className("custom-dropdown"));
    customDropdown.click();
    
    // Esperar a que aparezcan las opciones
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
    wait.until(ExpectedConditions.visibilityOfElementLocated(
        By.className("dropdown-options")));
    
    // Seleccionar opción específica
    List<WebElement> options = driver.findElements(By.className("dropdown-option"));
    
    options.stream()
        .filter(option -> "Premium Plan".equals(option.getText()))
        .findFirst()
        .ifPresentOrElse(
            WebElement::click,
            () -> fail("Opción 'Premium Plan' no encontrada")
        );
    
    // Verificar selección
    WebElement selectedDisplay = driver.findElement(By.className("selected-value"));
    assertEquals("Premium Plan", selectedDisplay.getText());
}

Validación de formularios

La validación de formularios representa un aspecto crítico en las pruebas automatizadas, ya que garantiza que los datos introducidos por los usuarios cumplan con los criterios establecidos antes de ser procesados. Las aplicaciones web modernas implementan validaciones tanto en el lado del cliente como del servidor, y Selenium WebDriver permite verificar ambos niveles de validación de manera sistemática.

Validación de campos obligatorios

Los campos obligatorios constituyen la primera línea de validación en cualquier formulario. Selenium permite verificar que estos campos implementen las restricciones correctas y muestren los mensajes de error apropiados cuando permanecen vacíos.

@Test
void testRequiredFieldValidation() {
    // Intentar enviar formulario con campos obligatorios vacíos
    WebElement nameField = driver.findElement(By.id("name"));
    WebElement emailField = driver.findElement(By.id("email"));
    WebElement submitButton = driver.findElement(By.id("submit"));
    
    // Dejar campos vacíos y enviar
    submitButton.click();
    
    // Verificar que el navegador previene el envío
    String nameValidationMessage = nameField.getAttribute("validationMessage");
    assertFalse(nameValidationMessage.isEmpty(), 
        "El campo nombre debería mostrar mensaje de validación");
    
    // Verificar atributo required en HTML5
    assertTrue(nameField.getAttribute("required") != null,
        "El campo nombre debería tener atributo required");
}

La validación HTML5 proporciona mecanismos nativos que los navegadores interpretan automáticamente. Es fundamental verificar que estos atributos estén correctamente configurados y que los mensajes de validación se muestren según las expectativas.

@Test
void testHTML5ValidationAttributes() {
    WebElement emailField = driver.findElement(By.id("email"));
    WebElement phoneField = driver.findElement(By.id("phone"));
    
    // Verificar tipos de input específicos
    assertEquals("email", emailField.getAttribute("type"));
    assertEquals("tel", phoneField.getAttribute("type"));
    
    // Introducir datos inválidos
    emailField.sendKeys("correo-invalido");
    phoneField.sendKeys("123abc");
    
    driver.findElement(By.id("submit")).click();
    
    // Verificar mensajes de validación del navegador
    String emailValidation = emailField.getAttribute("validationMessage");
    assertTrue(emailValidation.contains("@") || emailValidation.contains("email"),
        "Debería mostrar mensaje de formato de email inválido");
}

Validación de mensajes de error personalizados

Las validaciones personalizadas implementadas mediante JavaScript requieren técnicas específicas para verificar que los mensajes de error aparezcan correctamente y contengan la información apropiada para guiar al usuario.

@Test
void testCustomErrorMessages() {
    WebElement passwordField = driver.findElement(By.id("password"));
    WebElement confirmPasswordField = driver.findElement(By.id("confirm-password"));
    
    // Introducir contraseñas que no coinciden
    passwordField.sendKeys("MiContraseña123");
    confirmPasswordField.sendKeys("OtraContraseña456");
    
    driver.findElement(By.id("submit")).click();
    
    // Buscar mensaje de error específico
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
    WebElement errorMessage = wait.until(ExpectedConditions.visibilityOfElementLocated(
        By.className("password-error")));
    
    String errorText = errorMessage.getText();
    assertTrue(errorText.toLowerCase().contains("contraseñas no coinciden") ||
               errorText.toLowerCase().contains("passwords do not match"),
        "Mensaje de error debe indicar que las contraseñas no coinciden");
}

La verificación de múltiples errores requiere estrategias para manejar formularios complejos donde varios campos pueden fallar simultáneamente. Es importante verificar que todos los errores se muestren de manera coherente.

@Test
void testMultipleValidationErrors() {
    // Completar formulario con múltiples errores
    driver.findElement(By.id("name")).sendKeys("AB"); // Muy corto
    driver.findElement(By.id("email")).sendKeys("email-invalido"); // Sin @
    driver.findElement(By.id("age")).sendKeys("15"); // Menor de edad
    
    driver.findElement(By.id("submit")).click();
    
    // Recopilar todos los mensajes de error
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
    List<WebElement> errorElements = wait.until(driver -> {
        List<WebElement> errors = driver.findElements(By.className("error-message"));
        return errors.size() >= 3 ? errors : null;
    });
    
    // Verificar que se muestran errores para cada campo problemático
    List<String> errorMessages = errorElements.stream()
        .map(WebElement::getText)
        .filter(text -> !text.isEmpty())
        .toList();
    
    assertTrue(errorMessages.size() >= 3, 
        "Deberían mostrarse al menos 3 mensajes de error");
    
    // Verificar contenido específico de errores
    String allErrors = String.join(" ", errorMessages).toLowerCase();
    assertTrue(allErrors.contains("nombre") || allErrors.contains("name"));
    assertTrue(allErrors.contains("email") || allErrors.contains("correo"));
    assertTrue(allErrors.contains("edad") || allErrors.contains("age"));
}

Validación client-side vs server-side

Las validaciones del lado del cliente proporcionan retroalimentación inmediata al usuario, mientras que las validaciones del servidor garantizan la integridad de los datos. Es crucial probar ambos niveles para asegurar una experiencia de usuario completa y datos seguros.

@Test
void testClientSideValidation() {
    WebElement usernameField = driver.findElement(By.id("username"));
    
    // Introducir un nombre de usuario que debería ser validado en tiempo real
    usernameField.sendKeys("us");
    
    // Cambiar foco para activar validación
    driver.findElement(By.id("email")).click();
    
    // Verificar mensaje de validación inmediata
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));
    WebElement clientError = wait.until(ExpectedConditions.visibilityOfElementLocated(
        By.className("username-hint")));
    
    String hintText = clientError.getText();
    assertTrue(hintText.contains("mínimo") || hintText.contains("minimum"),
        "Debería mostrar mensaje sobre longitud mínima");
    
    // Corregir y verificar que el mensaje desaparece
    usernameField.clear();
    usernameField.sendKeys("usuario_valido");
    
    wait.until(ExpectedConditions.invisibilityOf(clientError));
}

Las validaciones del servidor requieren que el formulario se envíe para ser procesadas. Estas validaciones son fundamentales para verificar reglas de negocio complejas y restricciones de integridad de datos.

@Test
void testServerSideValidation() {
    // Completar formulario con datos que pasen validación client-side
    // pero fallen en server-side (ej: email ya registrado)
    driver.findElement(By.id("name")).sendKeys("Juan Pérez");
    driver.findElement(By.id("email")).sendKeys("juan.existente@empresa.com");
    driver.findElement(By.id("password")).sendKeys("ContraseñaSegura123!");
    
    driver.findElement(By.id("submit")).click();
    
    // Esperar respuesta del servidor
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    
    // Verificar que se muestra error del servidor
    WebElement serverError = wait.until(ExpectedConditions.visibilityOfElementLocated(
        By.className("server-error")));
    
    String errorText = serverError.getText();
    assertTrue(errorText.toLowerCase().contains("ya existe") ||
               errorText.toLowerCase().contains("already exists"),
        "Debería mostrar mensaje de email ya registrado");
    
    // Verificar que el formulario no se ha enviado exitosamente
    assertFalse(driver.getCurrentUrl().contains("success"),
        "No debería redirigir a página de éxito");
}

Validación de formatos específicos

Los formatos de datos requieren validaciones específicas que verifiquen patrones como números de teléfono, códigos postales, o identificadores únicos. Estas validaciones pueden implementarse tanto en cliente como en servidor.

@Test
void testFormatValidations() {
    WebElement phoneField = driver.findElement(By.id("phone"));
    WebElement postalCodeField = driver.findElement(By.id("postal-code"));
    
    // Probar formato de teléfono inválido
    phoneField.sendKeys("123");
    driver.findElement(By.id("submit")).click();
    
    // Verificar mensaje de formato
    WebElement phoneError = driver.findElement(By.className("phone-error"));
    assertTrue(phoneError.isDisplayed());
    
    // Corregir formato
    phoneField.clear();
    phoneField.sendKeys("612-345-678");
    
    // Probar código postal inválido
    postalCodeField.sendKeys("1234"); // Formato español requiere 5 dígitos
    driver.findElement(By.id("submit")).click();
    
    WebElement postalError = driver.findElement(By.className("postal-error"));
    assertTrue(postalError.isDisplayed());
    
    // Corregir y verificar
    postalCodeField.clear();
    postalCodeField.sendKeys("28001");
    
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));
    wait.until(ExpectedConditions.invisibilityOf(postalError));
}

Envío exitoso de formularios completos

La validación de envío exitoso requiere verificar que todos los campos pasen las validaciones y que el formulario se procese correctamente, incluyendo redirecciones, mensajes de confirmación, o cambios en el estado de la aplicación.

@Test
void testSuccessfulFormSubmission() {
    // Completar formulario con todos los datos válidos
    driver.findElement(By.id("name")).sendKeys("María García");
    driver.findElement(By.id("email")).sendKeys("maria.garcia@nuevo.com");
    
    Select countrySelect = new Select(driver.findElement(By.id("country")));
    countrySelect.selectByVisibleText("España");
    
    driver.findElement(By.id("phone")).sendKeys("654-321-987");
    driver.findElement(By.id("terms")).click(); // Aceptar términos
    
    WebElement submitButton = driver.findElement(By.id("submit"));
    submitButton.click();
    
    // Verificar envío exitoso mediante múltiples indicadores
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    
    // Opción 1: Redirección a página de éxito
    wait.until(driver -> driver.getCurrentUrl().contains("success") ||
                        driver.getCurrentUrl().contains("confirmation"));
    
    // Opción 2: Mensaje de confirmación en la misma página
    try {
        WebElement successMessage = wait.until(ExpectedConditions.visibilityOfElementLocated(
            By.className("success-message")));
        assertTrue(successMessage.getText().toLowerCase().contains("éxito") ||
                  successMessage.getText().toLowerCase().contains("success"));
    } catch (TimeoutException e) {
        // Si no hay mensaje, verificar por URL
        assertTrue(driver.getCurrentUrl().contains("success"),
            "Debería haber redirigido a página de éxito o mostrado mensaje de confirmación");
    }
}

Validación de formularios dinámicos

Los formularios dinámicos que cambian su estructura según las selecciones del usuario requieren estrategias de validación adaptativas que consideren los diferentes estados posibles del formulario.

@Test
void testDynamicFormValidation() {
    // Seleccionar tipo de usuario que muestra campos adicionales
    Select userTypeSelect = new Select(driver.findElement(By.id("user-type")));
    userTypeSelect.selectByVisibleText("Empresa");
    
    // Esperar a que aparezcan campos adicionales
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
    WebElement companyField = wait.until(ExpectedConditions.visibilityOfElementLocated(
        By.id("company-name")));
    WebElement taxIdField = driver.findElement(By.id("tax-id"));
    
    // Completar campos básicos pero dejar campos de empresa vacíos
    driver.findElement(By.id("name")).sendKeys("Representante Legal");
    driver.findElement(By.id("email")).sendKeys("representante@empresa.com");
    
    driver.findElement(By.id("submit")).click();
    
    // Verificar que se validan los campos dinámicos
    WebElement companyError = wait.until(ExpectedConditions.visibilityOfElementLocated(
        By.className("company-error")));
    
    assertTrue(companyError.isDisplayed(),
        "Debería mostrar error para campo de empresa obligatorio");
    
    // Completar campos dinámicos
    companyField.sendKeys("Empresa Ejemplo S.L.");
    taxIdField.sendKeys("B12345678");
    
    driver.findElement(By.id("submit")).click();
    
    // Verificar envío exitoso con campos dinámicos
    wait.until(driver -> driver.getCurrentUrl().contains("success"));
}

Verificación de estado de formulario

La verificación del estado del formulario incluye comprobar que los campos mantengan su estado durante la validación, que los datos no se pierdan al mostrar errores, y que la experiencia del usuario sea consistente.

@Test
void testFormStatePreservation() {
    String originalName = "Juan Pérez";
    String originalEmail = "juan@empresa.com";
    String invalidEmail = "email-invalido";
    
    // Completar formulario parcialmente con un error
    driver.findElement(By.id("name")).sendKeys(originalName);
    driver.findElement(By.id("email")).sendKeys(invalidEmail);
    driver.findElement(By.id("phone")).sendKeys(""); // Campo obligatorio vacío
    
    driver.findElement(By.id("submit")).click();
    
    // Verificar que los datos válidos se mantienen
    WebElement nameField = driver.findElement(By.id("name"));
    WebElement emailField = driver.findElement(By.id("email"));
    
    assertEquals(originalName, nameField.getAttribute("value"),
        "El nombre válido debería mantenerse después del error");
    assertEquals(invalidEmail, emailField.getAttribute("value"),
        "El email inválido debería mantenerse para que el usuario lo corrija");
    
    // Corregir errores
    emailField.clear();
    emailField.sendKeys(originalEmail);
    driver.findElement(By.id("phone")).sendKeys("612-345-678");
    
    driver.findElement(By.id("submit")).click();
    
    // Verificar envío exitoso
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    wait.until(driver -> driver.getCurrentUrl().contains("success"));
}

Aprendizajes de esta lección de Selenium

  • Comprender cómo interactuar con diferentes tipos de campos de formulario como inputs, textareas, checkboxes y radio buttons.
  • Aprender a utilizar la clase Select para manejar dropdowns nativos y personalizados.
  • Conocer técnicas para validar formularios, incluyendo campos obligatorios, mensajes de error personalizados y validaciones HTML5.
  • Diferenciar y probar validaciones del lado del cliente y del servidor.
  • Implementar estrategias para manejar formularios dinámicos y verificar el estado del formulario tras validaciones.

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