microsoft / WinAppDriver

Windows Application Driver
MIT License
3.69k stars 1.4k forks source link

FindElementByXPath will not work in a page object, throws WebDriverException before being passed to a custom wait method #1054

Open Tree55Topz opened 4 years ago

Tree55Topz commented 4 years ago

I had created the following post on StackOverflow looking for some solutions. I ended up finding out through my debugger that the issue was around using these lambda expressions for object identification in the page objects.

In the code on the post, the WebDriverException was being thrown in the actual page object not even getting to the WaitForObject method.

Does this style of element identification not work the same as the others. FindElementByName, FindElementByAccesibilityId both worked fine with the code (and it was a solution to wait for objects found on another issue here), it was only not working with the XPath approach.

https://stackoverflow.com/questions/60080984/can-not-catch-webdriverexception-for-certain-elements/60085041#60085041

angad16 commented 4 years ago

Hi @Tree55Topz you can try driver.findElementByXpath("//*[@Name='Menu']")

Tree55Topz commented 4 years ago

Ok but what is wrong with how I had it? The identifier worked fine. If I let the page load by doing a Thread.Sleep or something it eventually found and clicked the element.

My question is more based around why this is happening with my selector. Is it due to the contains? is it because I am specifying a Button type?

It seems to me like when you define an element by XPath it searches for the element right then and there, hence why it was failing before it was even passed to the WaitForObject method

angad16 commented 4 years ago

maybe it is because of the type Button.

Tree55Topz commented 4 years ago

identifying without specifying Button also led to the same result. It seems to be when using XPath in general

PandaMagnus commented 4 years ago

What version of WAD are you using? I've noticed earlier versions have some... occasionally unexpected behavior when using XPath. I upgraded to one version below the most recent and it works okay, but I still sometimes see weirdness like what you're describing. The newest version (which I haven't tried yet,) does have some improvements for XPath searches: https://github.com/microsoft/WinAppDriver/releases/tag/v1.2-RC

Might download that if you're not on it and see if that helps?

PandaMagnus commented 4 years ago

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

Tree55Topz commented 4 years ago

@PandaMagnus this worked - thanks for your help!