给定一个Selenium WebDriver元素实例,我想检查该元素是否与给定的CSS选择器匹配。该功能类似于jQuery的is()
函数。
我正在使用.NET
绑定。
示例(假设该方法将被称为Is
)
var links = _driver.FindElements(By.CssSelector("a"));
foreach (var link in links)
{
if (link.Is(".myclass[myattr='myvalue']"))
// ... do something
else
// ... do some other thing
}
是否有任何内置的东西来实现这一目标,或者如果没有,是否有人可以建议实施?我是Selenium的新手,还不知道。
更新
我发现没有内置方法可以做到这一点。我的最终目标是实现jQuery的parents(selector)
和closest(selector)
等方法,因此任何建议都会对这个更特殊的案例表示赞赏。
答案 0 :(得分:2)
没有Selenium方法可以完全相当于jQuery' s $(...).is(...)
。但是,DOM提供matches。它不是$(...).is(...)
的完全替代品,因为它不支持jQuery对CSS选择器语法的扩展,但是,Selenium也不支持这些扩展。
您可以通过将要测试的元素传递给传递给ExecuteScript
的JavaScript脚本来使用它。此元素将显示为脚本中arguments
的第一个元素。您只需在其上调用matches
并返回值即可。我不做C#,但根据文档,我相信它在C#中看起来像这样:
bool isIt = (bool)(driver as IJavaScriptExecutor).ExecuteScript(
"return arguments[0].matches(\".myclass[myattr='myvalue']\")", element);
isIt
包含测试结果。 element
是您要测试的元素,driver
是您已经创建的驱动程序。有关兼容性,请参阅caniuse。在我的应用程序中,我使用polyfill在我关心的所有平台上提供matches
。
这就是说我不建议循环遍历元素并逐个测试。问题是每个ExecuteScript
或GetAttribute
调用都是您的脚本和浏览器之间的往返。当您运行完整的测试套件时,这会增加,特别是如果浏览器在远离脚本的服务器场上运行。然后真的广告。我会构建您的测试,以便查询所有a
元素的列表以及所有a.myclass[myattr='myvalue']
元素的列表。这归结为两次往返。从这两个列表中,您可以获得进行if()
测试所需的所有信息。
答案 1 :(得分:1)
通常,为了比较硒中的元素,您可以比较它们的outerHTML
或innerHTML
表示。它不是防弹的,但应该在实践中起作用:
IWebElement elm = _driver.FindElement(By.CssSelector(".myclass[myattr='myvalue']"));
string linkHtml = link.GetAttribute("outerHTML");
string elmHtml = elm.GetAttribute("outerHTML");
if (linkHtml == elmHtml) {
...
}
请注意,在您的情况下,看起来您只需使用class
检查myattr
和GetAttribute()
属性的值:
string linkClass = link.GetAttribute("class");
string linkMyAttr = link.GetAttribute("myattr");
if (linkClass.Contains("myclass") && linkMyAttr == "myvalue") {
...
}
答案 2 :(得分:0)
我的最终解决方案是这三种方法:Parent, Parents(selector), Closest(selector)
。在此之后,可以很容易地实现其他几个类似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;
}