5

I have a view with the following structure:

GrandView
-Parent View1
-Parent View2
--Child View1
--Child View2

The child views take up almost all of the bounds of Parent View2, but there is still some space around the edges. I can select Parent View2 in the simulator with the accessibility inspector if I click on the edges. I can also tap Parent View2 in UIAutomation if I use:

tapWithOptions({tapOffset:{x:0.15, y:0.95}});

However, my calls to isVisible() always return 0. I expect that if I can tap the element, or select it with the accessibility inspector, it should return 1.

How does UIAutomation determine whether a UIAElement is visible?

Heath Borders
  • 30,998
  • 16
  • 147
  • 256

2 Answers2

0

If it's a UIView, it should be driven the the hidden property. If it's not a view, and it's a container, it should be driven by accessibilityElementsHidden .

In general though, you don't want to use this for UIAutomation. Instead, whatever you were going to do on the view - in this case, a tap() - go ahead and do it, and let the system throw an error if it times out. In general this is the model you want to follow in your scripts rather than testing whether something is available first. Sine UIAutomation is DOM scripting the UIAccessibility information, when things like animated view transitions happen things get out of sync. Sometimes the script executes faster than the UI animates, and sometimes the opposite! waitForInvalid may be a shortcut to a solution for you.

Alex Vollmer's tuneup.js library for UIAutomation makes writing tests much easier, and is easy to extend. https://github.com/alexvollmer/tuneup_js

prairiedogg
  • 6,323
  • 8
  • 44
  • 52
quellish
  • 21,123
  • 4
  • 76
  • 83
  • I'm seeing it driven by things other than the `hidden` and `accessibilityElementsHidden`, as implied by my question. I want to assert on the `isVisible()` property to ensure that a container is present without having to check contents of the container, which might change. – Heath Borders Jan 28 '12 at 06:16
0

Every operation you perform against an element has a timeout. This isn't obvious from the Apple documentation, but if you look at: setTimeout , it tells us:

The timeout value establishes a grace period for object resolution. If an object representing a UI element becomes available within the grace period, an attempt is made to instantiate that object from information retained by the instrument.

setTimeout itself just changes the default value (as do push and pop). What you really want to do is perform your action on your view, and fail on the timeout if it never becomes available (the default timeout is 5 seconds).
The WWDC 2010 session "Automating User Interface Testing with Instruments" does go into this a little, it's available on the ADC WWDC 2010 page, with both video and slides. In your case, you'd want to execute the tap() on your view. If, for some reason, that view isn't available to UIAutomation within 5 seconds, you should see an exception.
Experiment with changing the timeout by doing:

var oldTimeout = target.timeout(); target.pushTimeout(10);

before your code, and

target.popTimeout(oldTimeout);

after.

quellish
  • 21,123
  • 4
  • 76
  • 83
  • But again, I can't execute a `tap()` on my view. I can only execute a `tapWithOptions()`, as I mentioned in my question. However, I don't want to `tap()` my view because that will initiate actions I don't care about. I just want to know that it is present and tappable. – Heath Borders Jan 31 '12 at 06:47
  • Then instead of tap(), access a method like name(). Again, you're waiting for that action to time out. What you're really looking for is "is this view available within this timeout period". If the call to name() times out, it's not available. If your view is going to take more than the default 5 seconds to become available, use pushTimeout and popTimeout to extend the timeout. That tapWithOptions works isn't a surprise, the view is present but not yet available to automation as part of it's hierarchy (i.e. object resolution isn't done yet) – quellish Jan 31 '12 at 21:09
  • I don't think this is related to a timeout. I could sleep for 5 minutes and nothing would change here. I feel like this is related to other views obscuring my view. – Heath Borders Feb 01 '12 at 05:47
  • 1
    "Object resolution isn't done yet" means that while the view may be on screen, it is not available to UIAutomation yet. This is very common, and this is covered in the WWDC 2010 session on UIAutomation I pointed to earlier. – quellish Feb 03 '12 at 00:16
  • Even if your view is obscured it is in the view hierarchy, which is what you are dealing with in UIAutomation. – quellish Feb 03 '12 at 00:16
  • Yes, but I want to guarantee not just that my view is in the hierarchy but also that it is visible on screen. I have a lot of views that slide on and off at times. – Heath Borders Feb 03 '12 at 03:22
  • A view can be visible on screen but not yet available to UIAutomation (i.e. the object has not been resolved yet). When you attempt to use this view, whatever call you are making (i.e. name(), whatever) uses the timeout previously discussed. If the view has not resolved within that timeout, it's not available. If it has, you can tell wether that view is visible or not using isVisible(). UIAutomation deals with the view hierarchy, which may or may not be what you see on screen. It also often lags behind what you see on screen. Again, the WWDC video goes into this. – quellish Feb 03 '12 at 03:45
  • Couldn't I just assert checkIsValid() && isVisible() then? – Heath Borders Feb 03 '12 at 05:11