试图将IWebElement转换为By元素

时间:2016-04-27 11:22:50

标签: c# selenium selenium-webdriver casting

假设我有一个页面对象

[FindsBy(How = How.Id, Using = "buttonSignIn")] public IWebElement BtnSignin { get; set; }

我正在尝试将其传递给此方法,以将IWebElement转换为By元素。

public void MoveAndClick(IWebElement element)
{
    var findElement = driver.FindElement((By)element);

    Actions act = new Actions(driver);
    act.MoveToElement(findElement);
    act.Click(findElement);
    act.Perform();
}

我知道这段代码可以在不将元素转换为By元素的情况下工作,但是为了让我的测试工作,我需要弄清楚如何将IWebElement转换为{{1}元素。

当我运行它时,我得到一个null异常错误。有人有一个简单的解决方案吗?

4 个答案:

答案 0 :(得分:2)

简短的回答,这是不可能的。 Selenium的开发人员已经确定没有有用的用例。

答案 1 :(得分:1)

Selenium不提供IWebElement的选择器,但可以使用javascript创建选择器:

public static By ConvertToBy(this IWebElement element)
{
    if (element == null) throw new NullReferenceException();

    var attributes =
        ((IJavaScriptExecutor) SeleniumWebDriver.Driver).ExecuteScript(
            "var items = {}; for (index = 0; index < arguments[0].attributes.length; ++index) { items[arguments[0].attributes[index].name] = arguments[0].attributes[index].value }; return items;",
            element) as Dictionary<string, object>;
    if (attributes == null) throw new NullReferenceException();

    var selector = "//" + element.TagName;
    selector = attributes.Aggregate(selector, (current, attribute) =>
         current + "[@" + attribute.Key + "='" + attribute.Value + "']");

    return By.XPath(selector);
}

它将创建一个带有标记名称和所有attr名称和值的XPath,类似于:"//a[@class='test test-test'][@id='test-id'][@custom='custom-value']"

小心:由于没有正确的方法将IWebElement转换为By,如果页面中有另一个具有相同标记名称和attrs名称和值的元素,则扩展可以返回重复的结果

答案 2 :(得分:1)

我不推荐它,但您可以使用Reflection -

来完成此操作

在您的方法中,使用您的IWebElement&#39;元素&#39;参考:

//Get the RealProxy of the element
var elementProxy = System.Runtime.Remoting.RemotingServices.GetRealProxy(element);

//Get the Bys from the RealProxy:    
var bysFromElement = (IReadOnlyList<object>)elementProxy
    .GetType()
    .GetProperty("Bys", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public)?
    .GetValue(elementProxy);

//Convert bysFromElement to a list of strings for manipulation, or convert into a list of By objects, i.e.:       
var bys = new List<string>();
if (bysFromElement != null)
{
    bys.AddRange(bys.Select(@by => @by.ToString()));
}

然后你去了

答案 3 :(得分:0)

您可以使用获取元素的唯一属性:

IWebElement element = driver.FindElements(/* Example */By.Id("ID"));
String id = item.GetAttribute("id");
By elemBy = By.Id(id);