[英]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 元素。
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 元素。
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 元素。
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 元素。
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
With the availability of Chrome v96, google-chrome has made its shadow root return values compliant with the W3C WebDriver specification .随着 Chrome v96 的推出, google-chrome已使其影子根返回值符合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 ,我们需要使用新的影子根方法,如下所示:
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());
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"));
@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'
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.