Search code examples
c#seleniumexceptionappiumwinappdriver

Can not catch WebDriverException for certain elements


I have the following elements identified in a page object..

public WindowsElement usernameField => _session.FindElementByAccessibilityId("UserName");
public WindowsElement passwordField => _session.FindElementByAccessibilityId("Password");
public WindowsElement menuButton => _session.FindElementByXPath("//Button[contains(@Name, 'Menu')]");

I have a test with the following steps..

WaitForObject(usernameField)
usernameField.SendKeys("...")

WaitForObject(passwordField)
passwordField.SendKeys("...")

ClickButton("Sign In");

WaitForObject(menuButton);
menuButton.Click();

And below, here is my WaitForObject method..

// Wait for an Object to be accessible
public void WaitForObject(WindowsElement element)
{
       var wait = new DefaultWait<WindowsDriver<WindowsElement>>(_session)
       {
           Timeout = TimeSpan.FromSeconds(10),
           PollingInterval = TimeSpan.FromSeconds(1)
       };

       wait.IgnoreExceptionTypes(typeof(WebDriverException));
       wait.IgnoreExceptionTypes(typeof(InvalidOperationException));
       wait.IgnoreExceptionTypes(typeof(StaleElementReferenceException));
       wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
       wait.IgnoreExceptionTypes(typeof(NotFoundException));

       WindowsElement waitElement = null;

       wait.Until(driver =>
       {
           waitElement = element;

           return waitElement != null && waitElement.Enabled && waitElement.Displayed;
       });
}

The WaitForObject method works great for the usernameField & passwordField checks, but for some reason it fails immediately when passing in the menuButton. I know it was checking properly for usernameField & passwordField because I included some Console.WriteLines() to print out whenever it would detect one of those exceptions. As soon as it gets to the menuButton, nothing is logged it just fails immediately with a WebDriverException

OpenQA.Selenium.WebDriverException : An element could not be located on the page using the given search parameters.

Why would it not act the same for the menuButton? I have tried other approaches using while loops catching general Exceptions, but still it fails immediately when it gets to this element with a WebDriverException.

If I use a Thread.Sleep(10000) before trying to check for the element, it works fine and performs the click..

I am using WinAppDriver / Appium libraries.


Solution

  • Oh wait, sorry, I looked at your code more closely. Basically what's happening is because the method parameter is asking for the type itself, when C# goes to hand in the element to WaitForObject, it tries to evaluate the "WindowsElement menuButton" expression when it's handed to WaitForObject. By changing the WaitForObject method to accept a delegate, you'll defer that evaluation until you're inside the wait.

    You'll need to change your WaitForObject to be something like:

    public void WaitForObject(Func<WindowsElement> element)
    
    // Unchanged code here
    
    wait.Until(driver =>
           {
               waitElement = element();
    
               return waitElement != null && waitElement.Enabled && waitElement.Displayed;
           });
    

    THEN call it like: WaitForObject(() => menuButton); menuButton.Click();