C# 带阴影DOM的Selenium Webdriver

C# 带阴影DOM的Selenium Webdriver,c#,selenium,webdriver,shadow-dom,C#,Selenium,Webdriver,Shadow Dom,在C#中使用Selenium Webdriver时,我在尝试选择阴影DOM下存在的元素时遇到一个异常 我得到的例外是:NoTouchElementException 您建议如何将Selenium与ShadowDOM结合使用 谢谢 米哈尔 尝试这样定位您的元素: driver.FindElement(By.CssSelector('selector_otside_shadow_root /deep/ selector_inside_shadow_root')); IJavaScriptExec

在C#中使用Selenium Webdriver时,我在尝试选择阴影DOM下存在的元素时遇到一个异常

我得到的例外是:
NoTouchElementException

您建议如何将Selenium与ShadowDOM结合使用

谢谢

米哈尔


尝试这样定位您的元素:

driver.FindElement(By.CssSelector('selector_otside_shadow_root /deep/ selector_inside_shadow_root')); 
IJavaScriptExecutor js = (IJavaScriptExecutor)_driver;
var element = js.ExecuteScript("return document.querySelector('selector_outside_shadow_root').shadowRoot.querySelector('selector_inside_shadow_root');");
在您的情况下,它将是:

driver.FindElement(By.CssSelector('app-home /deep/ #itemName1'));
您可以在
chrome://downloads/
与此css\u选择器的链接:

downloads-manager /deep/ downloads-item /deep/ [id=file-link]
在开发工具中。正如您所看到的,需要传递两个
影子根
元素,因此请确保您只有一个
影子根
元素,或者像上面的示例一样使用多个
/deep/

或者您可以像这样使用JavaScipExecutor:

driver.FindElement(By.CssSelector('selector_otside_shadow_root /deep/ selector_inside_shadow_root')); 
IJavaScriptExecutor js = (IJavaScriptExecutor)_driver;
var element = js.ExecuteScript("return document.querySelector('selector_outside_shadow_root').shadowRoot.querySelector('selector_inside_shadow_root');");
  • 注意:据我所知,第一个建议仅适用于Chrome,如果您需要跨浏览器解决方案,请使用第二个

尝试这样定位您的元素:

driver.FindElement(By.CssSelector('selector_otside_shadow_root /deep/ selector_inside_shadow_root')); 
IJavaScriptExecutor js = (IJavaScriptExecutor)_driver;
var element = js.ExecuteScript("return document.querySelector('selector_outside_shadow_root').shadowRoot.querySelector('selector_inside_shadow_root');");
在您的情况下,它将是:

driver.FindElement(By.CssSelector('app-home /deep/ #itemName1'));
您可以在
chrome://downloads/
与此css\u选择器的链接:

downloads-manager /deep/ downloads-item /deep/ [id=file-link]
在开发工具中。正如您所看到的,需要传递两个
影子根
元素,因此请确保您只有一个
影子根
元素,或者像上面的示例一样使用多个
/deep/

或者您可以像这样使用JavaScipExecutor:

driver.FindElement(By.CssSelector('selector_otside_shadow_root /deep/ selector_inside_shadow_root')); 
IJavaScriptExecutor js = (IJavaScriptExecutor)_driver;
var element = js.ExecuteScript("return document.querySelector('selector_outside_shadow_root').shadowRoot.querySelector('selector_inside_shadow_root');");
  • 注意:据我所知,第一个建议仅适用于Chrome,如果您需要跨浏览器解决方案,请使用第二个

    • 我也有同样的问题。我发现了一些价值观

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


      我也有同样的问题。我发现了一些价值观

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


      一个非常好的存储库,它将Selenium shadow DOM交互编写为Java绑定:


      此repo使用一组jquerys来扩展和标识阴影dom中的元素。请看一看。将其移植到C#

      应该很容易,这是一个非常好的存储库,它以Java绑定的形式编写Selenium阴影dom交互:


      此repo使用一组jQuery来扩展和标识shadow dom中的元素。请看一看。应该很容易将其移植到C#

      您可以创建一个方法,该方法接受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;
          }
      }
      

      您可以创建一个方法,该方法接受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;
          }
      }
      

      不幸的是,第二个选项与我们的selenium基础设施不兼容。也许你还有其他建议?非常感谢,您使用的是哪种浏览器,请显示您尝试的第一个建议的代码。chrome和IE。我尝试了:driver.FindElement(By.XPath(“//app home/deep/div[@id='itemName1'])。单击()@迈克尔:对不起,我没有测试我的第一个建议。因此,它与css选择器一起工作。我不确定xPath,可能是不可能的。所以我已经编辑了我的答案,请看一看并尝试一下。此外,我还添加了一个示例链接和示例选择器,因此您可以尝试更多细节。我明白,现在它工作得很好!你知道它在Internet Explorer中是否也能工作吗?非常感谢!不幸的是,第二个选项与我们的selenium基础设施不兼容。也许你还有其他建议?非常感谢,您使用的是哪种浏览器,请显示您尝试的第一个建议的代码。chrome和IE。我尝试了:driver.FindElement(By.XPath(“//app home/deep/div[@id='itemName1'])。单击()@迈克尔:对不起,我没有测试我的第一个建议。因此,它与css选择器一起工作。我不确定xPath,可能是不可能的。所以我已经编辑了我的答案,请看一看并尝试一下。此外,我还添加了一个示例链接和示例选择器,因此您可以尝试更多细节。我明白,现在它工作得很好!你知道它在Internet Explorer中是否也能工作吗?非常感谢!是否在iframe中?是否在iframe中?