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
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.