C# 如何确定元素是否与CSS选择器匹配?

C# 如何确定元素是否与CSS选择器匹配?,c#,selenium,selenium-webdriver,C#,Selenium,Selenium Webdriver,给定一个SeleniumWebDriver元素实例,我想检查该元素是否与给定的CSS选择器匹配。该功能类似于jQuery的is()函数 我正在使用.NET绑定 示例(假设该方法将被称为Is) 是否有任何内置的东西来实现这一点,或者如果没有,有人能提出一个可能的实现方案吗?我是硒的新手,还不知道 更新 我看不出有什么内在的方法可以做到这一点。我的最终目标是实现像jQuery的父(选择器)和最近(选择器)这样的方法,因此对于这种更特殊的情况,任何建议都将受到欢迎。一般来说,为了比较selenium中

给定一个SeleniumWebDriver元素实例,我想检查该元素是否与给定的CSS选择器匹配。该功能类似于jQuery的
is()
函数

我正在使用
.NET
绑定

示例(假设该方法将被称为
Is

是否有任何内置的东西来实现这一点,或者如果没有,有人能提出一个可能的实现方案吗?我是硒的新手,还不知道

更新


我看不出有什么内在的方法可以做到这一点。我的最终目标是实现像jQuery的
父(选择器)
最近(选择器)
这样的方法,因此对于这种更特殊的情况,任何建议都将受到欢迎。

一般来说,为了比较selenium中的元素,您可以比较它们的
outerHTML
innerHTML
表示。它不是防弹的,但在实践中应该有效:

IWebElement elm = _driver.FindElement(By.CssSelector(".myclass[myattr='myvalue']"));

string linkHtml = link.GetAttribute("outerHTML");
string elmHtml = elm.GetAttribute("outerHTML");

if (linkHtml == elmHtml) {
    ...
}

请注意,在您的情况下,似乎可以使用
GetAttribute()
检查
class
myattr
属性的值:


没有任何Selenium方法可以与jQuery的
$(…).is(…)
等效。然而,DOM提供了一种新的方法。它不是
$(…)的完全替代品。它是(…)
,因为它不支持jQuery对CSS选择器语法的扩展,但Selenium也不支持这些扩展

您可以通过将要测试的元素传递给传递给
ExecuteScript
的JavaScript脚本来使用它。此元素将显示为脚本中
参数的第一个元素。您只需对其调用
匹配
,然后返回值。我不做C#但是根据文档,我相信在C#中会是这样的:

isIt
包含测试结果
element
是您要测试的元素,
driver
是您已经创建的驱动程序。有关兼容性,请参阅。在我的应用程序中,我使用polyfill在我关心的所有平台上提供
匹配



尽管如此,我不建议在元素上循环并逐个测试它们。问题是每个
ExecuteScript
GetAttribute
调用都是脚本和浏览器之间的往返。当您运行完整的测试套件时,这会增加,特别是当浏览器在远离脚本的服务器场上运行时。然后它真的登广告了。我将构造您的测试,以便它查询所有
a
元素的列表和所有
a.myclass[myattr='myvalue']
元素的列表。这归结为两次往返。从这两个列表中,您可以获得执行
if()
测试所需的所有信息。

我的最终解决方案是以下三种方法:
父级、父级(选择器)、最近的(选择器)
。在此之后,可以很容易地实现其他几个类似jQuery的助手方法。希望它能帮助将来的某个人

    public static IWebElement Parent(this IWebElement elem)
    {
        var script = new[]
        {
            "return",
            "  (function(elem) {",
            "     return elem.parentNode;",
            "   })(arguments[0]);"
        };
        var remoteWebElement = elem as RemoteWebElement;
        if (remoteWebElement == null)
            throw new NotSupportedException("This method is only supported on RemoteWebElement instances. Got: {0}".FormatWith(elem.GetType().Name));

        var scriptTxt = script.Implode(separator: " ");
        var scriptExecutor = remoteWebElement.WrappedDriver as IJavaScriptExecutor;
        if (scriptExecutor == null)
            throw new NotSupportedException("This method is only supported on drivers implementing IJavaScriptExecutor interface. Got: {0}".FormatWith(elem.GetType().Name));

        return scriptExecutor.ExecuteScript(scriptTxt, elem) as IWebElement;
    }

    public static ReadOnlyCollection<IWebElement> Parents(this IWebElement elem, string selector = null)
    {
        var script = new[]
        {
            "return",
            "  (function(elem) {",
            //"     console.log(elem);",
            "     var result = [];",
            "     var p = elem.parentNode;",
            "     while (p && p != document) {",
            //"       console.log(p);",
            (string.IsNullOrWhiteSpace(selector) ? null :
                "     if (p.matches && p.matches('" + selector + "'))"),
            "          result.push(p);",
            "       p = p.parentNode;",
            "     }",
            "     return result;",
            "   })(arguments[0]);"
        };
        var remoteWebElement = elem as RemoteWebElement;
        if (remoteWebElement == null)
            throw new NotSupportedException("This method is only supported on RemoteWebElement instances. Got: {0}".FormatWith(elem.GetType().Name));

        var scriptTxt = script.Implode(separator: " ");
        var scriptExecutor = remoteWebElement.WrappedDriver as IJavaScriptExecutor;
        if (scriptExecutor == null)
            throw new NotSupportedException("This method is only supported on drivers implementing IJavaScriptExecutor interface. Got: {0}".FormatWith(elem.GetType().Name));

        var resultObj = scriptExecutor.ExecuteScript(scriptTxt, elem) as ReadOnlyCollection<IWebElement>;
        if (resultObj == null)
            return new ReadOnlyCollection<IWebElement>(new List<IWebElement>());
        return resultObj;
    }

    public static IWebElement Closest(this IWebElement elem, string selector)
    {
        var script = new[]
        {
            "return",
            "  (function(elem) {",
            "     var p = elem;",
            "     while (p && p != document) {",
            "       if (p.matches && p.matches('" + selector + "'))",
            "          return p;",
            "       p = p.parentNode;",
            "     }",
            "     return null;",
            "   })(arguments[0]);"
        };
        var remoteWebElement = elem as RemoteWebElement;
        if (remoteWebElement == null)
            throw new NotSupportedException("This method is only supported on RemoteWebElement instances. Got: {0}".FormatWith(elem.GetType().Name));

        var scriptTxt = script.Implode(separator: " ");
        var scriptExecutor = remoteWebElement.WrappedDriver as IJavaScriptExecutor;
        if (scriptExecutor == null)
            throw new NotSupportedException("This method is only supported on drivers implementing IJavaScriptExecutor interface. Got: {0}".FormatWith(elem.GetType().Name));

        return scriptExecutor.ExecuteScript(scriptTxt, elem) as IWebElement;
    }
公共静态IWebElement父元素(此iWebElem)
{
var script=new[]
{
“返回”,
“(职能(要素){”,
“返回元素parentNode;”,
“}(参数[0]);”
};
var remoteWebElement=elem作为remoteWebElement;
if(remoteWebElement==null)
抛出新的NotSupportedException(“此方法仅在RemoteWebElement实例上受支持。获取:{0}.FormatWith(elem.GetType().Name));
var scriptTxt=script.intlode(分隔符:“”);
var scriptExecutor=remoteWebElement.WrappedDriver作为IJavaScriptExecutor;
if(scriptExecutor==null)
抛出新的NotSupportedException(“此方法仅在实现IJavaScriptExecutor接口的驱动程序上受支持。Get:{0}.FormatWith(elem.GetType().Name));
将scriptExecutor.ExecuteScript(scriptTxt,elem)作为IWebElement返回;
}
公共静态只读集合父级(此IWebElement元素,字符串选择器=null)
{
var script=new[]
{
“返回”,
“(职能(要素){”,
//“console.log(elem);”,
“var结果=[];”,
“var p=elem.parentNode;”,
“while(p&&p!=文档){”,
//“console.log(p);”,
(string.IsNullOrWhiteSpace(选择器)?null:
“如果(p.matches&&p.matches(“+selector+”)”)”,
“结果.推(p);”,
“p=p.parentNode;”,
"     }",
“返回结果;”,
“}(参数[0]);”
};
var remoteWebElement=elem作为remoteWebElement;
if(remoteWebElement==null)
抛出新的NotSupportedException(“此方法仅在RemoteWebElement实例上受支持。获取:{0}.FormatWith(elem.GetType().Name));
var scriptTxt=script.intlode(分隔符:“”);
var scriptExecutor=remoteWebElement.WrappedDriver作为IJavaScriptExecutor;
if(scriptExecutor==null)
抛出新的NotSupportedException(“此方法仅在实现IJavaScriptExecutor接口的驱动程序上受支持。Get:{0}.FormatWith(elem.GetType().Name));
var resultObj=scriptExecutor.ExecuteScript(scriptTxt,elem)作为只读集合;
if(resultObj==null)
返回新的ReadOnlyCollection(新列表());
返回结果j;
}
公共静态IWebElement最近(此IWebElement元素,字符串选择器)
{
var script=new[]
{
“返回”,
“(职能(要素){”,
“var p=elem;”,
“while(p&&p!=文档){”,
“如果(p.matches&&p.matches(““+selector+”)”)”,
“返回p;”,
“p=p.parentNode;”,
"     }",
"
string linkClass = link.GetAttribute("class");
string linkMyAttr = link.GetAttribute("myattr");

if (linkClass.Contains("myclass") && linkMyAttr == "myvalue") {
    ...
}
bool isIt = (bool)(driver as IJavaScriptExecutor).ExecuteScript(
    "return arguments[0].matches(\".myclass[myattr='myvalue']\")", element);
    public static IWebElement Parent(this IWebElement elem)
    {
        var script = new[]
        {
            "return",
            "  (function(elem) {",
            "     return elem.parentNode;",
            "   })(arguments[0]);"
        };
        var remoteWebElement = elem as RemoteWebElement;
        if (remoteWebElement == null)
            throw new NotSupportedException("This method is only supported on RemoteWebElement instances. Got: {0}".FormatWith(elem.GetType().Name));

        var scriptTxt = script.Implode(separator: " ");
        var scriptExecutor = remoteWebElement.WrappedDriver as IJavaScriptExecutor;
        if (scriptExecutor == null)
            throw new NotSupportedException("This method is only supported on drivers implementing IJavaScriptExecutor interface. Got: {0}".FormatWith(elem.GetType().Name));

        return scriptExecutor.ExecuteScript(scriptTxt, elem) as IWebElement;
    }

    public static ReadOnlyCollection<IWebElement> Parents(this IWebElement elem, string selector = null)
    {
        var script = new[]
        {
            "return",
            "  (function(elem) {",
            //"     console.log(elem);",
            "     var result = [];",
            "     var p = elem.parentNode;",
            "     while (p && p != document) {",
            //"       console.log(p);",
            (string.IsNullOrWhiteSpace(selector) ? null :
                "     if (p.matches && p.matches('" + selector + "'))"),
            "          result.push(p);",
            "       p = p.parentNode;",
            "     }",
            "     return result;",
            "   })(arguments[0]);"
        };
        var remoteWebElement = elem as RemoteWebElement;
        if (remoteWebElement == null)
            throw new NotSupportedException("This method is only supported on RemoteWebElement instances. Got: {0}".FormatWith(elem.GetType().Name));

        var scriptTxt = script.Implode(separator: " ");
        var scriptExecutor = remoteWebElement.WrappedDriver as IJavaScriptExecutor;
        if (scriptExecutor == null)
            throw new NotSupportedException("This method is only supported on drivers implementing IJavaScriptExecutor interface. Got: {0}".FormatWith(elem.GetType().Name));

        var resultObj = scriptExecutor.ExecuteScript(scriptTxt, elem) as ReadOnlyCollection<IWebElement>;
        if (resultObj == null)
            return new ReadOnlyCollection<IWebElement>(new List<IWebElement>());
        return resultObj;
    }

    public static IWebElement Closest(this IWebElement elem, string selector)
    {
        var script = new[]
        {
            "return",
            "  (function(elem) {",
            "     var p = elem;",
            "     while (p && p != document) {",
            "       if (p.matches && p.matches('" + selector + "'))",
            "          return p;",
            "       p = p.parentNode;",
            "     }",
            "     return null;",
            "   })(arguments[0]);"
        };
        var remoteWebElement = elem as RemoteWebElement;
        if (remoteWebElement == null)
            throw new NotSupportedException("This method is only supported on RemoteWebElement instances. Got: {0}".FormatWith(elem.GetType().Name));

        var scriptTxt = script.Implode(separator: " ");
        var scriptExecutor = remoteWebElement.WrappedDriver as IJavaScriptExecutor;
        if (scriptExecutor == null)
            throw new NotSupportedException("This method is only supported on drivers implementing IJavaScriptExecutor interface. Got: {0}".FormatWith(elem.GetType().Name));

        return scriptExecutor.ExecuteScript(scriptTxt, elem) as IWebElement;
    }