Frames, ventanas y pestañas

Intermedio
Selenium
Selenium
Actualizado: 18/04/2026

Frames e iframes en Selenium

Un frame (o iframe) es un documento HTML embebido dentro de otro documento. Selenium, por defecto, solo puede interactuar con el documento principal. Para acceder a elementos dentro de un frame, debes cambiar el contexto de ejecución.

Cambiar al frame por índice

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

WebDriver driver = new ChromeDriver();
driver.get("https://www.ejemplo.com/pagina-con-frames");

// Cambiar al primer frame (índice 0)
driver.switchTo().frame(0);

// Ahora puedes interactuar con elementos dentro del frame
driver.findElement(By.ID, "elemento-en-frame").click();

// Volver al documento principal
driver.switchTo().defaultContent();

Cambiar al frame por nombre o ID

// Por atributo name del frame
driver.switchTo().frame("nombre-del-frame");

// Por atributo id del frame (también funciona)
driver.switchTo().frame("id-del-frame");

// Interactuar con el frame
String textoEnFrame = driver.findElement(By.CSS_SELECTOR, "p.contenido").getText();

// Volver al contexto principal
driver.switchTo().defaultContent();

Cambiar al frame por WebElement

Esta es la forma más robusta porque permite usar esperas explícitas:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;

WebDriverWait espera = new WebDriverWait(driver, Duration.ofSeconds(10));

// Esperar a que el iframe esté disponible y cambiar a él
espera.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(
    By.CSS_SELECTOR, "iframe.mi-frame"
));

// Interactuar con elementos dentro del iframe
driver.findElement(By.ID, "campo-en-iframe").sendKeys("Hola desde iframe");

// Volver al documento principal
driver.switchTo().defaultContent();

Frames anidados

Cuando hay frames dentro de frames, se accede de forma progresiva:

// Cambiar al frame externo
driver.switchTo().frame("frame-externo");

// Cambiar al frame interno (dentro del frame externo)
driver.switchTo().frame("frame-interno");

// Interactuar con elementos en el frame interno
driver.findElement(By.ID, "elemento-anidado").click();

// Volver un nivel (al frame externo)
driver.switchTo().parentFrame();

// Volver al documento principal
driver.switchTo().defaultContent();

Patrón recomendado para frames

Encapsula la lógica de cambio de frame en métodos helper para mantener el código limpio:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
import java.util.function.Supplier;

public class FrameHelper {

    private final WebDriver driver;
    private final WebDriverWait espera;

    public FrameHelper(WebDriver driver) {
        this.driver = driver;
        this.espera = new WebDriverWait(driver, Duration.ofSeconds(10));
    }

    /**
     * Ejecuta una acción dentro de un frame y vuelve al contexto principal.
     */
    public <T> T ejecutarEnFrame(By localizadorFrame, Supplier<T> accion) {
        espera.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(localizadorFrame));
        try {
            return accion.get();
        } finally {
            driver.switchTo().defaultContent();
        }
    }
}

// Uso:
FrameHelper frameHelper = new FrameHelper(driver);
String texto = frameHelper.ejecutarEnFrame(
    By.id("mi-iframe"),
    () -> driver.findElement(By.CSS_SELECTOR, "p.contenido").getText()
);

Gestión de múltiples ventanas y pestañas

Cuando una acción abre una nueva ventana o pestaña, el WebDriver mantiene el foco en la ventana original. Debes cambiar manualmente el contexto.

Obtener todos los window handles

import java.util.Set;

// Guardar el handle de la ventana actual
String ventanaOriginal = driver.getWindowHandle();

// Hacer clic en un enlace que abre nueva ventana/pestaña
driver.findElement(By.LINK_TEXT, "Abrir en nueva ventana").click();

// Obtener todos los handles disponibles
Set<String> todosLosHandles = driver.getWindowHandles();
System.out.println("Ventanas abiertas: " + todosLosHandles.size());

// Cambiar a la nueva ventana (el handle diferente al original)
for (String handle : todosLosHandles) {
    if (!handle.equals(ventanaOriginal)) {
        driver.switchTo().window(handle);
        break;
    }
}

System.out.println("URL de la nueva ventana: " + driver.getCurrentUrl());

Abrir nueva pestaña o ventana con Selenium 4

Desde Selenium 4, puedes abrir programáticamente una nueva pestaña o ventana:

import org.openqa.selenium.WindowType;

// Abrir nueva pestaña y cambiar a ella
driver.switchTo().newWindow(WindowType.TAB);
driver.get("https://www.selenium.dev");
System.out.println("Nueva pestaña: " + driver.getTitle());

// Abrir nueva ventana (popup) y cambiar a ella
driver.switchTo().newWindow(WindowType.WINDOW);
driver.get("https://www.selenium.dev/documentation/");
System.out.println("Nueva ventana: " + driver.getTitle());

Cerrar ventana y volver al contexto original

// Guardar el handle original
String ventanaOriginal = driver.getWindowHandle();

// Abrir una nueva pestaña
driver.switchTo().newWindow(WindowType.TAB);
driver.get("https://www.selenium.dev");

// Hacer lo que necesitemos en la nueva pestaña
String tituloPestanaNueva = driver.getTitle();

// Cerrar la pestaña actual (NO el navegador completo)
driver.close();

// Volver a la ventana original
driver.switchTo().window(ventanaOriginal);
System.out.println("De vuelta en: " + driver.getCurrentUrl());

Esperar a que se abra una nueva ventana

import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
import java.util.Set;

// Guardar handles antes de la acción
Set<String> handlesPrevios = driver.getWindowHandles();

// Acción que abre nueva ventana/pestaña
driver.findElement(By.LINK_TEXT, "Ver detalles").click();

// Esperar hasta que haya más handles que antes
WebDriverWait espera = new WebDriverWait(driver, Duration.ofSeconds(10));
espera.until(d -> d.getWindowHandles().size() > handlesPrevios.size());

// Obtener el handle nuevo
String handleNuevo = driver.getWindowHandles().stream()
    .filter(h -> !handlesPrevios.contains(h))
    .findFirst()
    .orElseThrow(() -> new RuntimeException("No se abrió nueva ventana"));

driver.switchTo().window(handleNuevo);

Ejemplo completo: flujo con frames y ventanas

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
import java.util.Set;

import static org.junit.jupiter.api.Assertions.*;

class GestionFramesVentanasTest {

    private WebDriver driver;
    private WebDriverWait espera;

    @BeforeEach
    void setUp() {
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        espera = new WebDriverWait(driver, Duration.ofSeconds(10));
    }

    @AfterEach
    void tearDown() {
        if (driver != null) {
            driver.quit();
        }
    }

    @Test
    void debeInteractuarConElementosDentroDeFrame() {
        driver.get("https://www.ejemplo.com/pagina-con-frame");

        // Verificar que estamos en el documento principal
        assertTrue(driver.findElements(By.TAG_NAME, "header").size() > 0);

        // Cambiar al iframe
        espera.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(
            By.id("contenido-frame")
        ));

        // Interactuar con elemento dentro del frame
        var campo = driver.findElement(By.ID, "campo-frame");
        campo.sendKeys("Texto de prueba");

        // Volver al documento principal
        driver.switchTo().defaultContent();

        // Continuar con el documento principal
        var botonEnviar = driver.findElement(By.ID, "btn-enviar-principal");
        assertNotNull(botonEnviar);
    }

    @Test
    void debeGestionarMultiplesPestanas() {
        driver.get("https://www.ejemplo.com");
        String pestanaPrincipal = driver.getWindowHandle();

        // Abrir nueva pestaña
        driver.switchTo().newWindow(WindowType.TAB);
        driver.get("https://www.selenium.dev");

        // Verificar la nueva pestaña
        assertTrue(driver.getTitle().contains("Selenium"));

        // Cerrar la pestaña y volver a la principal
        driver.close();
        driver.switchTo().window(pestanaPrincipal);

        // Verificar que volvimos a la página original
        assertTrue(driver.getCurrentUrl().contains("ejemplo.com"));
        assertEquals(1, driver.getWindowHandles().size());
    }
}

Fuentes y referencias

Documentación oficial y recursos externos para profundizar en Selenium

Documentación oficial de Selenium
Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Selenium es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de Selenium

Explora más contenido relacionado con Selenium y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

Cambiar el contexto de ejecución a frames e iframes con switchTo().frame(). Volver al contexto principal con switchTo().defaultContent() y switchTo().parentFrame(). Gestionar múltiples ventanas y pestañas usando window handles. Abrir nuevas pestañas programáticamente con WindowType.TAB y WindowType.WINDOW. Cerrar ventanas/pestañas individuales y volver al contexto original. Combinar la gestión de frames y ventanas con esperas explícitas para robustez.