Если вы пытаетесь получить элемент «Очистить данные», вы можете использовать приведенные ниже js, чтобы получить элемент, а затем выполнить.
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')
Вот пример сценария.
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();
Редактировать 2: Объяснение
Проблема: Selenium не предоставляет явной поддержки для работы с Теневыми DOM-элементами , поскольку их нет в текущем dom. По этой причине мы получим исключение NoSuchElementException
при попытке доступа к элементам в shadow dom
.
Shadow DOM:
Примечание: мы будем ссылаться на термины, показанные на картинке. Пожалуйста, пройдите по картинке для лучшего понимания.
Решение:
Чтобы работать с теневым элементом , сначала мы должны найти shadow host
, к которому прикреплен теневой дом. Вот простой способ получить теневой корень на основе shadowHost.
private static WebElement getShadowRoot(WebDriver driver,WebElement shadowHost) {
JavascriptExecutor js = (JavascriptExecutor) driver;
return (WebElement) js.executeScript("return arguments[0].shadowRoot", shadowHost);
}
И затем вы можете получить доступ к элементу теневого дерева с помощью элемента 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"));
Для упрощения всех вышеперечисленных шагов создан метод, приведенный ниже.
public static WebElement getShadowElement(WebDriver driver,WebElement shadowHost, String cssOfShadowElement) {
WebElement shardowRoot = getShadowRoot(driver, shadowHost);
return shardowRoot.findElement(By.cssSelector(cssOfShadowElement));
}
Теперь вы можете получить элемент shadowTree одним вызовом метода
WebElement shadowHost = driver.findElement(By.cssSelector("shadowHost_CSS_Goes_here));
WebElement shadowTreeElement = getShadowElement(driver,shadowHost,"shadow_tree_element_css");
И выполняйте операции как обычно, как .click()
, .getText()
.
shadowTreeElement.click()
Это выглядит просто, когда у вас есть только один уровень DOM тени. Но здесь, в этом случае у нас есть несколько уровней теневых домов. Таким образом, мы должны получить доступ к элементу, достигнув каждого теневого хоста и корня.
Ниже приведен фрагмент кода с использованием методов, упомянутых выше (getShadowElement и 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();
Вы можете выполнить все вышеперечисленные шаги в одном вызове js, как уже упоминалось в начале ответа (добавлено ниже только для уменьшения путаницы).
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')");
Скриншот: