0

I have made a number of tests using Selenium with a Page Object Model pattern. I'm trying to pass a By so I can access an element by its name. However in my PageFactory.InitElements(excelSession, ribbon); method I get an exception of Type of member 'By' is not IWebElement or IList. Is there a way to get this method to accept By?

It seems like it will only an IWebElement parameter.

My code is as follows

 public class ExcelRibbon
    {
    [FindsBy(How = How.Name, Using = "Create")]
    [CacheLookup]
    public By Create { get; set; }
}

Where I receive my error

public static ExcelRibbon ribbon = new ExcelRibbon();
PageFactory.InitElements(excelSession,  ribbon);
webDriverWait.Until(ExpectedConditions.ElementExists(ribbon.Create));
webDriverWait.Until(ExpectedConditions.ElementToBeClickable(excelSession.FindElement(ribbon.Create))).Click();
3
  • I'm not sure what your "InitElements" is doing, but it looks like you aren't actually getting an element with your By. It says Excel, but I'm guessing this is a web page and not an actual excel file you are working with right? – mutt Aug 7 '17 at 21:23
  • InitElements is a method that Selenium has access to within the pageFactory class however this class is readonly so I can not make changes to it. I'm using an excel workbook in my tests. It was recommended by Microsoft as a testing tool for our product using the WinApp Driver – Craig Gallagher Aug 8 '17 at 8:10
  • 1
    ok, so from my understanding you need PageFactory.initElements(driver, page); which you are passing the "excelSession" and not a driver instance to and an excel ribbon and not a page to. I'm not sure if you have some additional plugin to support excel interactions or not. The methods in question look specific to a web page and your pulling excel elements so it throws the "not a web element" error when trying to cast the By location to web element or list of elements. Based on the info you would have to overload the class and add specific conversion logic from excel to a list<webelement>. – mutt Aug 8 '17 at 14:00
2

Unfortunately you can't do InitElements with a By. As the error indicates, objects initialized using a [FindBy] attribute have to be IWebElement or IList<IWebElement>.

This means that there are some ExpectedConditions that you will be unable to use with these objects since some ExpectedConditions require a By object.

There are a couple of ways around this, and I'm guessing you'll have to make adjustments as needed, since WinDriver probably isn't using IWebElements, but this should hopefully put you on the general right track:

  1. For that element, forget about initializing with PageFactory and just use By's with get methods. This way you can get the Element when you want to, but also use the By for some ExpectedConditions

Code:

protected By CreateBy { get; set; } = By.Name("Create");

//I'm showing IWebElement here, but your Element may be differing with WinDriver
protected IWebElement CreateElement()
{
    return excelSession.FindElement(CreateBy);
}
  1. Keep the [FindBy] using an IWebElement, and create custom Expected conditions for using IWebElement's

Code:

//Some base method that you can call wherever you need to wait for an element
public void WaitForElementToBeClickable(IWebElement element, int timeoutSeconds = 5)
{
    new WebDriverWait(excelSession, TimeSpan.FromSeconds(timeoutSeconds)).Until(d => 
    {
        try 
        {
            return element.Displayed && element.Enabled;
        }catch(NoSuchElementException)
        {
            return false;
        }
    });
}

I've had trouble getting this to work, but you should be able to use a FluentWait instead ignoring the NoSuchElement exception so you don't have to use a try catch.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.