Regarding IsUserVisible and IsHitTestVisible
Currently, the IsUserVisible function checks IsHitTestVisible but I'm not sure it should. IsHitTestVisible is a bit of a misnomer. It doesn't actually say anything about if the element is visible or not. It just says whether you can interact with it. It is true by default. Documentation here : https://msdn.microsoft.com/en-us/library/system.windows.uielement.ishittestvisible(v=vs.110).aspx#NotExistJustToMakeTheAElementVisible
We did a few tests with removing IsHitTestVisible from IsUserVisible. It works in most cases. The only case it didn't work was a case where we generate the components in the .cs file, rather than defining them in the XAML file. In this case, the driver would successfully get the correct coordinates and click at that position. But somehow the element wasn't ready and nothing happened. Since the driver just clicks a position, it reported a success and the test moved on to the next step Which of course failed because our application never reacted to the click. We also tried checking HitTestVisible with the .attribute command through Winium before clicking. But it reported it to true so that wasn't much of a help either.
It was working before we removed IsHitTestVisible, so when we debugged IsUserVisible we found that the IsHitTestVisible was set to false, even though we never set it ourselves. I'm not sure why this happens. But we found a workaround by implementing retry functionality for every step of the test.
So removing IsHitTestVisible would be the logical option, but here is still a chance that this might fail other tests. Otherwise there is no reason to use it as far as I can see. If you wanted to check IsHitTestVisible, you should use the .attribute() command.
There is a general problem with visibility determination and clicking.
The problem with visibility is that there are quite a few properties that affect visibility and there is no clear and simple API to get if element is actually visible, even IsOffscreen automation property does not work correctly in some basic situations.
The problem with clicking is in the fact that it us two-step operation: InnerServer, embedded into the app, determines coordinates for clicking and sends them over the wire to Driver to actually click it. This might result in driver clicking into wrong point, as element could have changed its position due to animations. Also we do not check directly if element is clickable, we just try to obtain a point inside element bounds that is visible on screen.
I think we should do the following or at try to research it:
- Use touch injection API to simulate touches on phone side, instead of doing them on host side (from driver), removing the need to pass coordinates over the wire and reducing chance of errors due to delay.
- Ensure that exception is raised if there is no clickable point.
- Research how we can improve and simplify visibility determination algorithm.
Also here are some docs on IsHitTestVisible https://msdn.microsoft.com/en-us/library/system.windows.uielement.ishittestvisible(v=vs.110).aspx
Another issue I have come across is when using AppBarButton. The AppBarButton gets places inside an AppBar or CommandBar. It seems that if you use the Page.BottomAppBar, the AppBar gets placed outside the Page control. It is placed nside a Grid with opacity set to 0. This causes the IsUserVisible to report anything inside that AppBar as not visible.
When iterating up the view hierarchy from the AppBar, I never hit the actual Page it belongs to, so it's unlikely that this is something we set ourselves. And even if we do set it ourselves somewhere, it's still visible so the function should return true.
I have implemented a function that iterates up the hierarchy until it hits the parent AppBar and checks if that's visible. I can post a pull request if desired.
Pull requests are welcome! It will also help me to better understand the problem and reproduce it. It would be especially nice if you could provide a test that will fail on current master build and will work after PR is applied.