如何使用硒自动实现阴影DOM元素?

时间:2019-04-19 12:24:29

标签: javascript java selenium polymer shadow-dom

我正在使用Java Selenium项目进行网页自动化。网页包含许多我无法使用硒findElement方法与之交互的多层影子根DOM元素。

我尝试了以下解决方案:

  • 深层CSS(不适用于最新的chrome浏览器)
  • JS执行器。 (这确实很繁琐,并且维护起来很复杂)

注意:

如果您知道我可以在Selenium Java框架中实现的除上面列出的之外的任何其他解决方案,请传递该解决方案。在此先感谢!。

3 个答案:

答案 0 :(得分:1)

使用 Selenium v​​3.x ChromeDriver v2.46 演示阴影DOM 自动化 > Chrome v73.x 这是一个简单的程序,它打开URL chrome://downloads/,并使用executeScript()方法发送字符序列 pdf 作为搜索框中的搜索文字

  • 代码块:

    import org.openqa.selenium.By;
    import org.openqa.selenium.JavascriptExecutor;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.chrome.ChromeDriver;
    import org.openqa.selenium.chrome.ChromeOptions;
    
    public class shadow_DOM {
    
        static WebDriver driver;
        public static void main(String[] args) 
        {   
            System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
            ChromeOptions options = new ChromeOptions();
            options.addArguments("start-maximized");
            //options.addArguments("disable-infobars");
            options.addArguments("--disable-extensions"); 
            driver = new ChromeDriver(options);
            driver.get("chrome://downloads/");
            WebElement root1 = driver.findElement(By.tagName("downloads-manager"));
            WebElement shadow_root1 = expand_shadow_element(root1);
    
            WebElement root2 = shadow_root1.findElement(By.cssSelector("downloads-toolbar#toolbar"));
            WebElement shadow_root2 = expand_shadow_element(root2);
    
            WebElement root3 = shadow_root2.findElement(By.cssSelector("cr-toolbar#toolbar"));
            WebElement shadow_root3 = expand_shadow_element(root3);
    
            WebElement root4 = shadow_root3.findElement(By.cssSelector("cr-toolbar-search-field#search"));
            WebElement shadow_root4 = expand_shadow_element(root4);
    
            WebElement search_term = shadow_root4.findElement(By.cssSelector("div#searchTerm input#searchInput"));
            String js = "arguments[0].setAttribute('value','pdf')";
            ((JavascriptExecutor) driver).executeScript(js, search_term);
    
            WebElement search_button = shadow_root4.findElement(By.cssSelector("paper-icon-button#icon"));
            search_button.click();
    
            System.out.println("Search Button Clicked");
        }
    
        public static WebElement expand_shadow_element(WebElement element)
        {
            WebElement shadow_root = (WebElement)((JavascriptExecutor)driver).executeScript("return arguments[0].shadowRoot", element);
            return shadow_root;
        }
    
    }
    
  • 控制台输出:

    Search Button Clicked
    
  • 浏览器快照:

shadowDOM


Outro

根据Determine the fate of experimental '>>>' combinator >>> 组合器中的讨论,它代替了 /deep/ 组合器,用于刺穿所有不推荐使用阴影DOM样式边界,该边界已在Blink中的标志后面实现。

答案 1 :(得分:1)

有一个非常好的插件可以与硒项目link一起使用。它有助于编写更好,易读和可维护的代码。使用此功能,您可以访问多级影子DOM(最多4级)。这使用简单的CSS选择器来识别元素。

WebElement findElement(String cssSelector):如果要从DOM中获取单个元素,请使用此方法

List<WebElement> findElements(String cssSelector):如果要从DOM中查找所有元素,请使用此

WebElement findElements(WebElement parent, String cssSelector):如果要从父对象DOM中查找单个元素,请使用此

List<WebElement> findElements(WebElement parent, String cssSelector):如果要从父对象DOM中查找所有元素,请使用此

WebElement getShadowElement(WebElement parent,String selector):如果要从父DOM中查找单个元素,请使用此

List<WebElement> getAllShadowElement(WebElement parent,String selector):如果要从父DOM中查找所有元素,请使用此

boolean isVisible(WebElement element):如果要查找元素的可见性,请使用此

boolean isChecked(WebElement element):如果要检查是否选中了复选框,请使用此

boolean isDisabled(WebElement element):如果要检查元素是否已禁用,请使用此

String getAttribute(WebElement element,String attribute):如果要获取属性(如aria-selected)和元素的其他自定义属性,请使用此选项。

void selectCheckbox(String label):使用它来选择带有标签的复选框元素。

void selectCheckbox(WebElement parentElement, String label):使用它来选择带有标签的复选框元素。

void selectRadio(String label):使用它来使用标签选择单选元素。

void selectRadio(WebElement parentElement, String label):使用它可以使用标签从父DOM中选择单选元素。

void selectDropdown(String label):使用此选项可使用标签选择下拉列表项(如果UI上仅存在或加载了一个下拉菜单,则使用此选项)。

void selectDropdown(WebElement parentElement, String label):使用它可以使用标签从父DOM中选择下拉列表项。

如何使用此插件: 您将不得不依赖您的项目。

Maven

<dependency>
  <groupId>io.github.sukgu</groupId>
  <artifactId>automation</artifactId>
  <version>0.0.4</version>
<dependency>

对于位于卷影根dom元素下的html标签

<properties-page id="settingsPage"> 
  <textarea id="textarea">
</properties-page>

您可以在框架中使用此代码来获取textarea元素Object。

  import io.github.sukgu.*;
  Shadow shadow = new Shadow(driver);
  WebElement element = shadow.findElement("properties-page#settingsPage>textarea#textarea");
  String text = element.getText();

答案 2 :(得分:0)

使用JSExecutor和CSS找出影子DOM元素的步骤:

  1. 找出基础元素,即“阴影”根元素的父元素。

  2. 获取该元素的Shadow根。

  3. 并在该影子根网络元素上找到您的元素

    示例:

<div id="example">
#shadow-root
<div id="root" part="root">
   <div id="label" part="label">ShadowRootLabel</div>
</div>
</ptcs-label>

#找出阴影根元素的方法

public WebElement getShadowRootElement(WebElement element) {
WebElement ele = (WebElement) ((JavascriptExecutor)driver)
    .executeScript("return arguments[0].shadowRoot", element);
        return ele;
    }

#Step1示例,即找到基本元素:

WebElement root1 = driver.findElement(By.id("example"));

#Step2

//Get shadow root element
WebElement shadowRoot1 = getShadowRootElement(root1);

#Step3-我们需要使用CSS选择器找到位于影子根目录内的元素,xpath在这里不起作用

//Here we will get Element inside Shadow Dom Element
WebElement shadowElement = shadowRoot3.findElement(By.cssSelector("div[id=label]"));