Calabash iOS how to tap the back button item - ios

Guys just cant figure out how to tap on BackButtonItem from Navigation Bar with Calabash framework, I'm setting accessibilityLabel like this:
self.navigationItem.leftBarButtonItem?.accessibilityLabel = "goBack"
and trying to test it like this with no luck:
touch("* marked:'goBack'")
touch_transition('navigationItemButtonView first',
"* marked:'#{goBack}'")

The problem is that UINavigationItem, UITabBarItem, and UIToobarItem are converted, at runtime, to Views. For example, a UITabBarItem is converted to a UIToobarButton. In the conversion, the accessibilityIdentifier and accessibilityLabel are not preserved.
# This will probably get you the left navbar button
query("UINavigationItemButtonView index:0")
There are ways to enforce that an accessibilityIdentifier is preserved, such as making the navigation item from a custom view.
Take a look at the briar bars/navbar.rb for inspiration. I do not recommend using briar in your project; its life is uncertain (I am the maintainer).

I'd recommend trying query "all * marked:'goBack'" and if that still doesn't return any results, just try a query "all *" and see if the label shows up in the results.
You could also try setting the accessibilityIdentifier of the view - generally that's the preferred way to set up views for automation.

Just updating it might be helpful for someone who wish to use default back button
touch('navigationItemButtonView first')
This will take you back.
Found from calabash predefined steps.

Related

Which control should I use to display an ActionSheet-like view at the top of the screen?

I was asked to display a list of three options for the user in a View sliding from the top to bottom. They say it should slide from the top because the action is initiated from a dropdown-like button on the navigation bar.
Most of what I found on that subject mentions the deprecated UIActionSheet class.
The "new" way using UIAlertController doesn't seem to allow us to change position of the view. At the least from what I've found.
The end result I'm trying to get can be seen on the image below,
From what I've learned about iOS programming, one method I could think to achieve that would be to create a new UIViewController and to use a custom class to control the transition. But it just seems so much. And I think it wouldn't not look like a dropdown afterall.
The other option would be to create the TableView with options and leave it on the Controller where it should be displayed, configuring its height to zero. And then Animating when necessary. I also have such a bad feeling doing it this way.
Is there a right way to do this on iOS? Does one of the options I've found seems acceptable?
Thanks.
Following the suggestion given by #Losiowaty on the comments, I started looking for a custom View/Control on cocoapods and ended up finding quite a few that did what I was looking.
The one I decided to use is this:
https://github.com/lminhtm/LMDropdownView

Does setting a button's UIAccessibilityTrait remove the word "button" from it's accessibilityLabel?

I ran into a weird situation just now. I have a container view in our app which needs to read out all of the views when tapped, but only one view should be able to be accessed individually. Because some of the views are complex views with their own subviews, I setup my ADA logic to read the accessibilityLabel of a view if it has one, and if not, to build one from the subviews.
Well, today we had to add the word "button" to the help button when it's being read because the container view was tapped. So I simply added the word "button" to the label's accessibilityLabel and everything worked fine. Then I realized, this may change it to read "more information button button" when tapped individually, since I had set the accessibilityTraits property of the button to be UIAccessibilityTraitButton.
However, to my surprise, it read it correctly as "more information button." Does Apple detect extraneous "button's" in an accessibilityLabel and remove them when the trait is set to be a button? Would they also remove extraneous "label's" from a button when it's trait is set to be a label? I find this extremely cool, and incredible forethought on Apple's engineer's parts, if this is the way it works.
Edit: If this is the way it's done, could someone point me to where this is documented? I wasn't able to find it, although I'm currently still working on this fix so I didn't do the most in depth search I could have done.
I've had some time now to do some proper testing. VoiceOver will remove the extra labels if you set the traits properly. This allows for you to have the type read in a container view, and still set an accessibilityTraits.
So, for example, if you set the accessibilityTraits to UIAccessibilityTraitButton and the last word in your accessibilityLabel is button, it will remove the last word and only read button once. If, however, you set the accessibilityTraits to `UIAccessibilityTraitImage', it will not remove the button, and will end its reading with "button image". Changing the last word to "image", however, has it only read image once.
Pretty nice forethought on Apple's part with that implementation.

Swift UIButton - How to remove underline?

I have problem when in iOS settings is enabled this setting "Button Shapes"
It causing this underline in application (first picture with enabled setting, second without)
Any idea how to programatically or in storyboard disable it?
I tried attributed text but I get same result :(
I'm newbie in Swift.
Thanks for help!
It's not a problem. You should not make any attempt to counter any accessibility changes set by the user. They are there for a reason.
This is an answer by user4291543 from this question Remove underline on UIButton in iOS 7
[yourBtnHere setBackgroundImage:[[UIImage alloc] init] forState:UIControlStateNormal];
I found this answer works with SWFrameButton
And for all the others saying "Don't Do This", SWFrameButton is a very good example of when you would want to do this. I also think the OP's situation is a perfectly valid scenario as well...
I totally agree with #maddy's comment:
It's not a problem. You should not make any attempt to counter any accessibility changes set by the user. They are there for a reason.
But I did stumble on a way to accomplish the task at hand...
In addition to a UIButton, you'll also need to make a .png file that contains nothing (meaning the entire contents have an opacity of 0%). Go ahead and load that into your xcode project's assets.
Now go ahead and set the Button's Background to that image you just provided. (In my case, I called it clear) This will remove the underline from the button's text. However, now you can't see the boundaries of the button. This can be solved by changing the Background of the button's View. Go ahead and select any color for the View's Background property and now the background of the View visibly defines the button's boundaries. You're able to see this because your clear.png has an opacity of 0%.
see the Attributes inspector for UIButton here.
Rather than trying to defeat the underline by going to make a label perform some action via UITapGestureRecognizer, this allows you to still use a UIButton. Keeping inline with accessibility features to mark buttons for people that want to do that.
You could create a custom button class with a label (with clear color). If you set the text of this label instead it shouldn`t get an underline.
Are you sure you want to do that?
Apple added an accessibility feature to mark buttons for people that want to do that. Apple will probably reject your app because it defeats a system function meant to help the disabled.
I found the solution. All you have to do is set a picture as the background of the button. just pick a picture with the same color as the button you created.

Prevent UISegmentedControl segment selection on focus on tvOS

I'm working on a simple UI on a tvOS app and I'm facing a strange problem.
When a UISegmentedControl get focused you can move your focus around and it automatically changes the selected segment. But what I'm looking for is a way to limit the segment selection only when the user taps the segment, not when he focused it.
Any idea?
Thanks in advance.
You need to have your own internal variable for the selected segment and only change its value when the select button is pressed (which you can get using a gesture recognizer). When the segment loses focus (detectable in didUpdateFocus function) you assign the value of your internal variable to the selected index of the segment control.
You need to subclass UISegmentedControl then override didUpdateFocusInContext. In the "Custom Class" field in IB use the name of your custom class.
You can subclass UISegmentedControl and disable the behavior by defining:
#objc func _selectFocusedSegment(){
print ("select focused segment")
}
Beware that this solution is a hack. As far as I know there is no good, clean way to accomplish what you want short of steering clear of UISegmentedControl.
Also know that when a UISegmentedControl 'changes focus' between segments, it does not actually change focus. So hooking into focus updates like Nostradamus is suggesting will not work. To the focus engine UISegmentedControl behaves like a single large focusable element, not like a group of focusable segments. You can see this for yourself by debug inspecting a UIFocusUpdateContext on focusing towards or away from a UISegmentedControl.
I stumbled onto _selectFocusedSegment by defining a UISegmentedControl subclass and debug logging the various NSObject.perform methods, among others. My intent was to reverse engineer how UISegmentedControl retains a sticky last focused item, which is quite difficult to do on Apple TV. I was not able to find out exactly how UISegmentedControl manages focus, but I was able to find the answer to your question along the way.

Accessing nested UIElements in Xcode 7 UI Testing

I am having trouble locating XCUIElements on a screen for the app I am testing. I realize you can access a button for example via something like:
app.buttons[].elementBoundByIndex(0)
But the problem is sometimes, the component is not found. Like in a case where I have a Button in a cell in a UITableView. I try to make an XCUIElementQuery to find the button, and it is not there. I try to look for tables or tableviews or collection views and even though they are in the view controller, they are not found in UI Testing. The count of the returned array will be zero.
I attempted originally to record the test, but clicking the element I am trying to access did not work. Xcode detected it as an "Other Element" and when trying to tap during, playback the application does not advance.
Is there a high level way to access a component like a UIView high in the UI hierarchy to cascade down?
I didn't know this at the time, but what I was looking for was basically debugDescription:
Set a breakpoint when you hit the area you're trying to debug. Then
po print(app.debugDescription)
in the debug console. You will see the hierarchy then.
Ideally you should set an accessibilityIdentifier on your button and search for it via that. The accessibilityIdentifier should be unique for elements on the screen. You can set an accessibilityIdentifier in the Identity Inspector in Interface Builder (command-option-3) or in code directly. Once you have one, the query looks like:
app.buttons["SomeAccessibilityIdentifier"]
Ryan Poolos answer was the best answer for me as it solved my issue with nested UI Elements
We had to solve it by removing a few accessibility identifiers on superviews in the stack. Not ideal but did get it working without changing actual functionality. – Ryan Poolos
So with that in mind, I found the xib file with the element in question, selected the element, selected the tab "Show the Identity Inspector" on the right panel and unchecked the Accessibility checkbox.
I then did a recording of the element which resulted in:
[[[[[XCUIApplication alloc] init].scrollViews.tables childrenMatchingType:XCUIElementTypeOther] elementBoundByIndex:index] childrenMatchingType:XCUIElementTypeButton].element;
Notice how XCUIElementTypeOther is in the query. This was not the case when the accessibility identifiers were enabled as I would get:
[[[[[XCUIApplication alloc] init].scrollViews.tables.otherElements containingType:XCUIElementTypeStaticText identifier:#"username"] childrenMatchingType:XCUIElementTypeButton].element tap];
Obviously I wouldnt know the username as it would always change and this was a major problem. But after removing the accessibility identifiers,
containingType:XCUIElementTypeStaticText identifier:#"username"
changed to
childrenMatchingType:XCUIElementTypeOther] elementBoundByIndex:index
SUCCESS :)
In my own experience you being able to find an element (an UIView in your case as UIButton inherits from UIview) through its accessibilityIdentifier depends on how you added it to the view.
I assume that in your case you added the button to the cell programatically with addSubView. If that's the case, probably you will not be able to access to it. I've had the same problem and asked the question here but no proper solution at the moment, so my advice is try to avoid adding views with addSubView the moment...

Resources