Trying to convert IWebElement into a By element

[亡魂溺海] 提交于 2019-12-12 03:28:36

问题


Lets say I have a page object

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

I am trying to pass that into this method to convert the IWebElement into a By element.

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

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

I know that this piece of code will work without casting the element into a By element, however for my tests to work I need to figure out how to convert the IWebElement into a By element.

When I run this I get a null exception error. Does anyone have a simple solution for this?


回答1:


Short answer, this is not possible. The developers of Selenium have decided that there are no useful use cases for this.




回答2:


Selenium does not provide us the selector of a IWebElement, but is possible create an selector using 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);
}

It will create an XPath with the tag name and all attr names and values, something like it: "//a[@class='test test-test'][@id='test-id'][@custom='custom-value']"

Be carefull: as not have a right way to transform a IWebElement into a By, the extension can return duplicated results if in the page has another element with the same tag name and attrs names and values




回答3:


I wouldn't recommend it, but you can accomplish this using Reflection --

Inside your method, using your IWebElement 'element' reference:

//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()));
}

and there you go




回答4:


You can use get an unique attribute of an element :

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


来源:https://stackoverflow.com/questions/36888327/trying-to-convert-iwebelement-into-a-by-element

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!