I’m working on an automated test with Java + Maven + Selenium WebDriver + Serenity BDD + Cucumber.

The test needs to click the "Download" button of the most recent projection file in a table that is rendered inside an iframe.


Problem

At runtime, my step fails with this assertion:

No se encontró la tabla bodyArchivos ni en el DOM principal ni en ninguno de los iframes de la página. Revisa que la URL sea la de 'Archivos de resultados de proyecciones' y que el id sea exactamente 'bodyArchivos'.

Serenity output (Cucumber scenario):


Descargar y validar archivo de proyección ya existente
\-----------------------------------------------------------------------
23:33:03.045 ERROR \[ main\] : Test failed at step: Y descargo el archivo de proyección más reciente
23:33:03.045 ERROR \[ main\] : No se encontró la tabla bodyArchivos ni en el DOM principal ni en ninguno de los iframes de la página. Revisa que la URL sea la de 'Archivos de resultados de proyecciones' y que el id sea exactamente 'bodyArchivos'.
Failed scenarios:
.../archivos_proyeccion.feature:24 # Descargar y validar archivo de proyección ya existente
java.lang.AssertionError: No se encontró la tabla bodyArchivos ni en el DOM principal ni en ninguno de los iframes de la página. Revisa que la URL sea la de 'Archivos de resultados de proyecciones' y que el id sea exactamente 'bodyArchivos'.
 at org.af.gestion.mi.pension.stepdefinitions.ArchivosProyeccionStepDefinitions.cambiarAFrameConTablaArchivos(ArchivosProyeccionStepDefinitions.java:407)
 at org.af.gestion.mi.pension.stepdefinitions.ArchivosProyeccionStepDefinitions.descargoArchivoMasReciente(ArchivosProyeccionStepDefinitions.java:202)
 at ?.descargo el archivo de proyección más reciente(.../archivos_proyeccion.feature:27)

So my helper method cannot find tbody#bodyArchivos either in the main DOM or in any iframe, but in the browser DevTools the element does exist.

Step definition that fails

@Cuando("descargo el archivo de proyección más reciente")
public void descargoArchivoMasReciente() {
 WebDriver driver = getDriver();
 WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(40));
 // 1) Switch to the frame (or main DOM) that contains the table
 cambiarAFrameConTablaArchivos(driver);
 // 2) Wait for the table in the CURRENT context
 WebElement tabla = wait.until(
 ExpectedConditions.presenceOfElementLocated(By.id("bodyArchivos"))
 );
 // 3) Get the first row (most recent file) and its download button
 WebElement fila = tabla.findElement(By.cssSelector("tr:first-child"));
 WebElement botonDescarga = fila.findElement(By.cssSelector("td:nth-child(3) > button"));
 // Click using JS in case of overlays
 ((JavascriptExecutor) driver).executeScript("arguments[0].click();", botonDescarga);
 // 4) Go back to main content for the next steps
 driver.switchTo().defaultContent();
 // (code that waits for the downloaded .csv is omitted)
}

Helper method to switch into the iframe

/**
 * Looks for tbody#bodyArchivos either in the main DOM or inside any iframe.
 * If found, it leaves the driver already switched to the correct context.
 * Otherwise it throws an AssertionError.
 */
private void cambiarAFrameConTablaArchivos(WebDriver driver) {
 // Always start from the main document
 driver.switchTo().defaultContent();
 System.out.println("[DescargaCSV] URL actual: " + driver.getCurrentUrl());
 // 1) First try in the main DOM (no iframe)
 List<WebElement> tablasEnPrincipal = driver.findElements(By.id("bodyArchivos"));
 if (!tablasEnPrincipal.isEmpty()) {
 System.out.println("[DescargaCSV] ✔ Tabla bodyArchivos encontrada en el DOM principal (sin iframe).");
 return;
 }
 // 2) If not in main DOM, look into iframes
 List<WebElement> iframes = driver.findElements(By.tagName("iframe"));
 System.out.println("[DescargaCSV] iframes encontrados en la página: " + iframes.size());
 if (iframes.isEmpty()) {
 throw new AssertionError(
 "No se encontró la tabla bodyArchivos ni en el DOM principal ni en iframes (no hay iframes en la página)."
 );
 }
 // 3) Try each iframe by index
 for (int i = 0; i < iframes.size(); i++) {
 try {
 driver.switchTo().defaultContent();
 driver.switchTo().frame(i);
 List<WebElement> tablas = driver.findElements(By.id("bodyArchivos"));
 if (!tablas.isEmpty()) {
 System.out.println("[DescargaCSV] ✔ Tabla bodyArchivos encontrada en iframe index=" + i);
 return; // stay in this iframe
 } else {
 System.out.println("[DescargaCSV] iframe index=" + i + " no contiene bodyArchivos");
 }
 } catch (NoSuchFrameException e) {
 System.out.println("[DescargaCSV] NoSuchFrameException en iframe index=" + i);
 } catch (StaleElementReferenceException e) {
 System.out.println("[DescargaCSV] StaleElementReference en iframe index=" + i +
 " → ignoring and continuing with the next one");
 }
 }
 // 4) If we get here, the table was not found anywhere
 throw new AssertionError(
 "No se encontró la tabla bodyArchivos ni en el DOM principal ni en ninguno de los iframes de la página. " +
 "Revisa que la URL sea la de 'Archivos de resultados de proyecciones' y que el id sea exactamente 'bodyArchivos'."
 );
}

HTML structure (iframe + table)

From the Elements tab in DevTools, the page has this iframe:

<iframe
 name="ifrcontent"
 id="ifrcontent"
 src="/PortalAccesoWeb/jsp/templates/blank.jsp"
 class="min-width: 500px;"
 width="100%"
 height="450px"
 frameborder="0"
 allowtransparency="yes">
</iframe>

When I expand that iframe in DevTools, I see that its document loads another URL and contains the form and the table I need:

<div class="col-md-12">
 <div class="card-table">
 <h5 class="text-center text-white">Archivos de resultados de proyecciones</h5>
 </div>
 <div>
 <table class="table mb-0">
 <caption class="text-end pb-0">Últimos archivos de resultados</caption>
 <thead>
 <tr class="tdtituloAz mx-2">
 <th class="align-middle">Archivo</th>
 <th class="align-middle text-center">Fecha fin procesamiento</th>
 <th class="align-middle text-center">Descargar</th>
 </tr>
 </thead>
 <tbody id="bodyArchivos">
 <tr class="trTablaImpar">
 <td class="align-middle">ProyeccionPensionISSSTE_260925_resultado_58.csv</td>
 <td class="align-middle text-center">26/09/2025</td>
 <td class="align-middle text-center">
 <button class="btn btn-secondary btn-sm" type="button"
 onclick="descargarProyeccion('ProyeccionPensionISSSTE_260925_resultado_58.csv');">
 <i class="fa fa-file-excel-o"></i>
 </button>
 </td>
 </tr>
 <!-- several more <tr> rows ... -->
 </tbody>
 </table>
 </div>
</div>

Browser console output

In the browser console I tried:

document.querySelectorAll("iframe")
document.querySelectorAll("iframe").length

and I get:

  • NodeList []
  • 0

I also tried:

let frame = window.frames[0];
frame.document.getElementById("bodyArchivos");

and I get:

Uncaught TypeError: Cannot read properties of undefined (reading 'document')

At the same time, in the Console I see a JavaScript error coming from the application:

Uncaught ReferenceError: setUpArchivos is not defined at onload (archivos.do:48)

What I have already tried

  • Iterating all iframes by index (driver.switchTo().frame(i)) and searching for By.id("bodyArchivos") in each one.
  • Looking for the table in the main DOM before switching to frames.
  • Confirming in DevTools that the id really is bodyArchivos and that the table is inside ifrcontent.
  • Running the test in Edge and Chrome with the same result.

Question

What am I doing wrong when trying to locate tbody#bodyArchivos inside this iframe?

  • Is there something special about this iframe because its src is /PortalAccesoWeb/jsp/templates/blank.jsp but internally it loads /ProyeccionPensionWeb/archivos.do?
  • Could the JavaScript error (setUpArchivos is not defined) prevent the iframe document from being attached to window.frames / document.querySelectorAll("iframe") from Selenium’s point of view?
  • Do I need a different strategy to switch into this iframe (for example by name or WebElement, or waiting for the inner document to be fully loaded) so that WebDriver can see tbody#bodyArchivos?enter image description hereenter image description here

1 Reply 1

// 2) Wait for the table in the CURRENT context
 WebElement tabla = wait.until(
 ExpectedConditions.presenceOfElementLocated(By.id("bodyArchivos"))
 );

You are waiting for the element after you've already thrown an exception that it doesn't exist. Move the wait inside your helper.

Your Reply

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Reply", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.