简体   繁体   English

如何使用 selenium 自动化影子 DOM 元素?

[英]How to automate shadow DOM elements using selenium?

I am using Java Selenium project for web page automation.我正在使用 Java Selenium 项目进行 web 页面自动化。 The web page contains lots of multi-level shadow-root DOM elements that I am not able to interact with using selenium findElement method. web 页面包含许多我无法使用 selenium findElement方法与之交互的多级阴影根 DOM 元素。

I have tried the following solutions:我尝试了以下解决方案:

  • deep css (Don't work on latest chrome browser)深度 css(不适用于最新的 chrome 浏览器)
  • JS Executor. JS执行器。 (This is really tedious and becomes complex to maintain) (这真的很繁琐,维护起来也很复杂)

Note:笔记:

If you know any other solution other than listed above that I can implement in Selenium Java framework, please pass on the solution.如果您知道除上面列出的任何其他解决方案,我可以在 Selenium Java 框架中实现,请传递解决方案。 Thanks in advance..提前致谢..

I am using Java Selenium project for web page automation.我正在使用 Java Selenium 项目进行网页自动化。 The web page contains lots of multi-level shadow-root DOM elements that I am not able to interact with using selenium findElement method.该网页包含许多我无法使用 selenium findElement方法与之交互的多级 shadow-root DOM 元素。

I have tried the following solutions:我尝试了以下解决方案:

  • deep css (Don't work on latest chrome browser) deep css(不适用于最新的 chrome 浏览器)
  • JS Executor. JS 执行器。 (This is really tedious and becomes complex to maintain) (这真的很乏味,维护起来也很复杂)

Note:笔记:

If you know any other solution other than listed above that I can implement in Selenium Java framework , please pass on the solution.如果您知道我可以在 Selenium Java 框架中实现的除上面列出的任何其他解决方案,请传递该解决方案。 Thanks in advance !.提前致谢 !。

I am using Java Selenium project for web page automation.我正在使用 Java Selenium 项目进行网页自动化。 The web page contains lots of multi-level shadow-root DOM elements that I am not able to interact with using selenium findElement method.该网页包含许多我无法使用 selenium findElement方法与之交互的多级 shadow-root DOM 元素。

I have tried the following solutions:我尝试了以下解决方案:

  • deep css (Don't work on latest chrome browser) deep css(不适用于最新的 chrome 浏览器)
  • JS Executor. JS 执行器。 (This is really tedious and becomes complex to maintain) (这真的很乏味,维护起来也很复杂)

Note:笔记:

If you know any other solution other than listed above that I can implement in Selenium Java framework , please pass on the solution.如果您知道我可以在 Selenium Java 框架中实现的除上面列出的任何其他解决方案,请传递该解决方案。 Thanks in advance !.提前致谢 !。

I am using Java Selenium project for web page automation.我正在使用 Java Selenium 项目进行网页自动化。 The web page contains lots of multi-level shadow-root DOM elements that I am not able to interact with using selenium findElement method.该网页包含许多我无法使用 selenium findElement方法与之交互的多级 shadow-root DOM 元素。

I have tried the following solutions:我尝试了以下解决方案:

  • deep css (Don't work on latest chrome browser) deep css(不适用于最新的 chrome 浏览器)
  • JS Executor. JS 执行器。 (This is really tedious and becomes complex to maintain) (这真的很乏味,维护起来也很复杂)

Note:笔记:

If you know any other solution other than listed above that I can implement in Selenium Java framework , please pass on the solution.如果您知道我可以在 Selenium Java 框架中实现的除上面列出的任何其他解决方案,请传递该解决方案。 Thanks in advance !.提前致谢 !。

With Selenium 4 there is now WebElement.getShadowRoot() . Selenium 4 现在有了WebElement.getShadowRoot() For example:例如:

driver.findElement(By.id("parentId")).getShadowRoot().findElement(By.cssSelector( "label" )).findElement(By.tagName("input"))

As normal with a #shadow-root , the navigation choices for the next hop are limited.#shadow-root一样,下一跳的导航选择是有限的。 Eg against Chrome By.cssSelector() and By.className() are valid, but By.id() and By.tagName() fail with org.openqa.selenium.InvalidArgumentException: invalid argument: invalid locator例如,针对 Chrome By.cssSelector()By.className()是有效的,但是By.id()By.tagName()失败并出现org.openqa.selenium.InvalidArgumentException: invalid argument: invalid locator

Shadow DOM in Selenium Selenium 中的影子 DOM

With the availability of Chrome v96, has made its shadow root return values compliant with the W3C WebDriver specification .随着 Chrome v96 的推出, 已使其影子根返回值符合W3C WebDriver 规范

As @titusfortner mentions in their comment :正如@titusfortner在他们的评论中提到的那样:

Now that Chrome supports shadow root via the driver, shadowRoot JS calls are returned per the spec with a shadow root element key (shadow-6066-11e4-a52e-4f735466cecf).现在 Chrome 通过驱动程序支持影子根,shadowRoot JS 调用将根据规范返回,并带有影子根元素键 (shadow-6066-11e4-a52e-4f735466cecf)。 Selenium 4 has a new ShadowRoot class to support this, but we didn't include the translation code that we do when execute script calls return elements. Selenium 4 有一个新的 ShadowRoot class 来支持这一点,但我们没有包括我们在执行脚本调用返回元素时所做的翻译代码。 This has been fixed and will be available in Selenium 4.1.此问题已得到修复,并将在 Selenium 4.1 中提供。

The only difference is that you'll need to cast to ShadowRoot instead of WebElement.唯一的区别是您需要转换为 ShadowRoot 而不是 WebElement。

So moving forward using Selenium with Microsoft Edge and Google Chrome v96 and greater, we need to use the new shadow root method as follows:因此,在 Microsoft Edge 和 Google Chrome v96 及更高版本中继续使用Selenium ,我们需要使用新的影子根方法,如下所示:

  • Java example : Java 示例

     driver.get("http://watir.com/examples/shadow_dom.html"); WebElement shadowHost = driver.findElement(By.cssSelector("#shadow_host")); SearchContext shadowRoot = shadowHost.getShadowRoot(); WebElement shadowContent = shadowRoot.findElement(By.cssSelector("#shadow_content")); Assertions.assertEquals("some text", shadowContent.getText());
  • Python example : Python 示例

     driver.get('http://watir.com/examples/shadow_dom.html') shadow_host = driver.find_element(By.CSS_SELECTOR, '#shadow_host') shadow_root = shadow_host.shadow_root shadow_content = shadow_root.find_element(By.CSS_SELECTOR, '#shadow_content') assert shadow_content.text == 'some text'
  • C# example : C# 示例

     _driver.Navigate().GoToUrl("http://watir.com/examples/shadow_dom.html"); var shadowHost = _driver.FindElement(By.CssSelector("#shadow_host")); var shadowRoot = shadowHost.GetShadowRoot(); var shadowContent = shadowRoot.FindElement(By.CssSelector("#shadow_content"));
  • Ruby example : Ruby 示例

     @driver.get('http://watir.com/examples/shadow_dom.html') shadow_host = @driver.find_element(css: '#shadow_host') shadow_root = shadow_host.shadow_root shadow_content = shadow_root.find_element(css: '#shadow_content') expect(shadow_content.text).to eq 'some text'

tl; tl; dr博士

Read more at:阅读更多:

I can access of multi-level of shadow-root DOM elements using this recursive function.我可以使用这个递归 function 访问多级阴影根 DOM 元素。

private getHTMLElementWithShadowRoot(htmlElement: HTMLElement, nameHtmlElements: string[]): HTMLElement {
            if (nameHtmlElements.length === 0) return htmlElement;
            return this.getHTMLElementWithShadowRoot(
                htmlElement.shadowRoot ?
                    htmlElement.shadowRoot.querySelector(nameHtmlElements[0]) :
                    htmlElement.querySelector(nameHtmlElements[0]), nameHtmlElements.slice(1)
            );
 }

I use in this way:我以这种方式使用:

let appComponent = document.body.querySelector("app-component") as HTMLElement;
let appHeader = this.getHTMLElementWithShadowRoot(appComponent, ["main-component", "header-component", "#app-header"]);

Here you can see the DOM在这里你可以看到 DOM 在此处输入图像描述

You have to write the underline names in the array string nameHtmlElements without the first name, since the first name is passed in the first parameter of the function.您必须在数组字符串 nameHtmlElements 中写入下划线名称,而不需要名字,因为名字是在 function 的第一个参数中传递的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM