Hola usuario de nuestra página web, hemos encontrado la respuesta a lo que buscas, desplázate y la hallarás más abajo.
Solución:
Si está tratando de obtener el elemento ‘Borrar datos’, puede usar el siguiente js para obtener el elemento y luego realizarlo.
return document.querySelector('settings-ui').shadowRoot.querySelector('settings-main').shadowRoot.querySelector('settings-basic-page').shadowRoot.querySelector('settings-section > settings-privacy-page').shadowRoot.querySelector('settings-clear-browsing-data-dialog').shadowRoot.querySelector('#clearBrowsingDataDialog').querySelector('#clearBrowsingDataConfirm')
Aquí está el guión de muestra.
driver.get("chrome://settings/clearBrowserData");
driver.manage().window().maximize();
JavascriptExecutor js = (JavascriptExecutor) driver;
WebElement clearData = (WebElement) js.executeScript("return document.querySelector('settings-ui').shadowRoot.querySelector('settings-main').shadowRoot.querySelector('settings-basic-page').shadowRoot.querySelector('settings-section > settings-privacy-page').shadowRoot.querySelector('settings-clear-browsing-data-dialog').shadowRoot.querySelector('#clearBrowsingDataDialog').querySelector('#clearBrowsingDataConfirm')");
// now you can click on clear data button
clearData.click();
Edición 2: Explicación
Problema: Selenium no proporciona soporte explícito para trabajar con elementos Shadow DOM, ya que no están en el dom actual. Esa es la razón por la que obtendremos NoSuchElementException
excepción al intentar acceder a los elementos en el shadow dom
.
Sombra DOM:
Nota: Nos referiremos a los términos que se muestran en la imagen. Así que por favor revise la imagen para una mejor comprensión.
Solución:
Para trabajar con elemento de sombra primero tenemos que encontrar el shadow host
al que se adjunta el shadow dom. Aquí está el método simple para obtener la raíz sombra basada en shadowHost.
private static WebElement getShadowRoot(WebDriver driver,WebElement shadowHost)
JavascriptExecutor js = (JavascriptExecutor) driver;
return (WebElement) js.executeScript("return arguments[0].shadowRoot", shadowHost);
Y luego puede acceder al elemento del árbol de la sombra usando el elemento shadowRoot.
// get the shadowHost in the original dom using findElement
WebElement shadowHost = driver.findElement(By.cssSelector("shadowHost_CSS"));
// get the shadow root
WebElement shadowRoot = getShadowRoot(driver,shadowHost);
// access shadow tree element
WebElement shadowTreeElement = shadowRoot.findElement(By.cssSelector("shadow_tree_element_css"));
Para simplificar todos los pasos anteriores, creó el siguiente método.
public static WebElement getShadowElement(WebDriver driver,WebElement shadowHost, String cssOfShadowElement)
WebElement shardowRoot = getShadowRoot(driver, shadowHost);
return shardowRoot.findElement(By.cssSelector(cssOfShadowElement));
Ahora puede obtener el elemento shadowTree con una sola llamada de método
WebElement shadowHost = driver.findElement(By.cssSelector("shadowHost_CSS_Goes_here));
WebElement shadowTreeElement = getShadowElement(driver,shadowHost,"shadow_tree_element_css");
Y realice las operaciones como de costumbre como .click()
, .getText()
.
shadowTreeElement.click()
Esto parece simple cuando solo tienes un nivel de shadow DOM. Pero aquí, en este caso, tenemos múltiples niveles de sombras. Así que tenemos que acceder al elemento llegando a cada host y raíz de la sombra.
A continuación se muestra el fragmento utilizando los métodos mencionados anteriormente (getShadowElement y getShadowRoot)
// Locate shadowHost on the current dom
WebElement shadowHostL1 = driver.findElement(By.cssSelector("settings-ui"));
// now locate the shadowElement by traversing all shadow levels
WebElement shadowElementL1 = getShadowElement(driver, shadowHostL1, "settings-main");
WebElement shadowElementL2 = getShadowElement(driver, shadowElementL1,"settings-basic-page");
WebElement shadowElementL3 = getShadowElement(driver, shadowElementL2,"settings-section > settings-privacy-page");
WebElement shadowElementL4 = getShadowElement(driver, shadowElementL3,"settings-clear-browsing-data-dialog");
WebElement shadowElementL5 = getShadowElement(driver, shadowElementL4,"#clearBrowsingDataDialog");
WebElement clearData = shadowElementL5.findElement(By.cssSelector("#clearBrowsingDataConfirm"));
System.out.println(clearData.getText());
clearData.click();
Puede lograr todos los pasos anteriores en una sola llamada js como se menciona al comienzo de la respuesta (agregado a continuación solo para reducir la confusión).
WebElement clearData = (WebElement) js.executeScript("return document.querySelector('settings-ui').shadowRoot.querySelector('settings-main').shadowRoot.querySelector('settings-basic-page').shadowRoot.querySelector('settings-section > settings-privacy-page').shadowRoot.querySelector('settings-clear-browsing-data-dialog').shadowRoot.querySelector('#clearBrowsingDataDialog').querySelector('#clearBrowsingDataConfirm')");
Captura de pantalla:
Puedes añadir valor a nuestra información tributando tu experiencia en las anotaciones.