带有影子DOM的Selenium Web驱动程序

vcudknz3  于 2023-01-20  发布在  其他
关注(0)|答案(6)|浏览(122)

在C#中使用Selenium Webdriver时,我在尝试选择存在于Shadow DOM下的元素时遇到异常。
我得到的例外是:NoSuchElementException
您建议如何将Selenium与Shadow DOM一起使用?
谢谢你,
米哈尔

zynd9foi

zynd9foi1#

尝试按如下方式定位元素:

driver.FindElement(By.CssSelector('selector_otside_shadow_root /deep/ selector_inside_shadow_root'));

在您情况下,它将是:

driver.FindElement(By.CssSelector('app-home /deep/ #itemName1'));

您可以使用以下css_selectorchrome://downloads/链接中测试此方法:

downloads-manager /deep/ downloads-item /deep/ [id=file-link]

正如你所看到的,需要传递两个shadow-root元素,所以确保你只有一个shadow-root元素,或者像上面的例子一样使用多个/deep/
也可以像这样使用JavasciptExecutor:

IJavaScriptExecutor js = (IJavaScriptExecutor)_driver;
var element = js.ExecuteScript("return document.querySelector('selector_outside_shadow_root').shadowRoot.querySelector('selector_inside_shadow_root');");

****注:***据我所知,第一个建议只适用于Chrome,如果你想要一个跨浏览器的解决方案-使用第二个。

af7jpaap

af7jpaap2#

您可以创建一个方法,该方法接受ShadowDom根定位器列表,并构建js脚本来执行和获取shadow元素:

public static IWebElement GetElementFromShadowDom(this IWebDriver driver, params string[] selectors)
    {
        IJavaScriptExecutor js = (IJavaScriptExecutor)driver;

        var scriptString = "return document.querySelector";
        var selectorIndex = 0;
        var stopIndex = selectors.Length - 1;

        foreach (var selector in selectors)
        {
            var root = "('" + selector + "')";
            root += (selectorIndex != stopIndex && selectors.Length != 1) ? ".shadowRoot.querySelector" : null;                
            selectorIndex++;
            scriptString += root;
        }

        var webElement = (IWebElement)js.ExecuteScript(scriptString);
        return webElement;
    }
}
s3fp2yjn

s3fp2yjn3#

我遇到了同样的问题。我在

Inspect -> Properties -> value (it can be something else)

试试看:

WebElement element = driver.findElement(By.cssSelector("div"));
System.out.println(element.getAttribute("value"));
zvokhttg

zvokhttg4#

一个非常好的存储库,具有以Java绑定形式编写的Selenium shadow DOM交互:https://github.com/sukgu/shadow-automation-selenium
这个repo使用了一堆JQuery来扩展和识别shadow dom中的元素。请看一下。应该很容易移植到C#

hgtggwj0

hgtggwj05#

这会导致错误安德烈,我不知道现在该怎么办:异常提示:javascript错误:参数列表(会话信息:微软边缘服务器=104.0.1293.63)
改为:

var element = js.ExecuteScript("return document.querySelector('#shadow-root').shadowRoot.querySelector('#private-host');");

但结果是异常提示:javascript错误:无法读取null的属性(阅读“shadowRoot”)

lfapxunr

lfapxunr6#

在影子DOM中查找元素的规则

1.首先使用普通的查找元素方法查找Shadow Root元素(也称为Shadow Host)的父元素。
1.调用下面的帮助器方法,通过传递Shadow HostElement来找到影子根元素。使用下面的帮助器方法。
1.在嵌套的影子根的情况下。保持重复上述两个步骤。即再次找到 * 影子主机,然后影子根
1.如果你有元素的ID,那么使用影子根元素,找到你想要执行动作的元素,然后在它上面执行你想要的动作。
1.如果ID不可用-您可以使用除XPath之外的任何其他标识符
**(XPath在影子DOM中不起作用)。***

  • 您也可以使用SelectorsHub插件获取定位器和示例代码 *
    帮助器方法1
/// <summary>
    /// Method 1 to fetch Shadow Root using Selenium's in build method
    /// </summary>
    /// <param name="shadowHostElement">IWebElement - Which is parent element of Shadow Root element. Also called Shadow Host</param>
    /// <returns>Shadow Root element in the form of ISearchContext</returns>
    public static ISearchContext GetShadowRootElement(IWebElement shadowHostElement)
    {
        ISearchContext shadowRootElement = shadowHostElement.GetShadowRoot();
        return shadowRootElement;
    }

帮助器方法2

/// <summary>
    /// Method 2 to fetch Shadow Root using Selenium's IJavaScriptExecutor
    /// </summary>
    /// <param name="driver">Instance of IWebDriver</param>
    /// <param name="shadowHostElement">IWebElement - Which is parent element of Shadow Root element. Also called Shadow Host</param>
    /// <returns>Shadow Root element in the form of ISearchContext</returns>
    public static ISearchContext GetShadowRootElementUsingJavaScript(IWebDriver driver, IWebElement shadowHostElement)
    {
        IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
        ISearchContext shadowRootElement = (ISearchContext)js.ExecuteScript("return arguments[0].shadowRoot", shadowHostElement);

        return shadowRootElement;
    }

示例代码-Website with Shadow DOM

//1. Finding shadow host first - normally using FindElement            
IWebElement ShadowHostElement = Driver.FindElement(By.TagName("book-app"));
        
//2. Finding Shadow Root using Shadow Host element - use either one from below

ISearchContext shadowRoot = GetShadowRootElementUsingJavaScript(Driver, ShadowHostElement);
        ISearchContext shadowRoot = GetShadowRootElement(ShadowHostElement);

        IWebElement node = shadowRoot.FindElement(By.Id("input"));
        node.SendKeys("Something");

相关问题