EachNavigationBar
EachNavigationBar copied to clipboard
Help needed: BackItem broken for UITests
Since bringing this (fantastic) library in, my UI test has failed when trying to press the back button in the navigation bar. Do you know if there is a trick to getting it tappable at all?
I used to have app.navigationBars.buttons.element(boundBy: 0).tap()
, but that is now failing with
Failed to synthesize event: Failed to scroll to visible (by AX action) Button, label: 'Back', error: Error kAXErrorCannotComplete performing AXAction 2003 on element AX element pid: 15737, elementOrHash.elementID: 105553178871296.256. (Underlying Error: Error kAXErrorCannotComplete performing AXAction 2003 on element AX element pid: 15737, elementOrHash.elementID: 105553178871296.256)
Any help appreciated. Thanks a lot Luke
Which version are you using?
My podlock file shows 1.15.0
Can I have a look at your code?
Sure.
Ignore the custom Colour.
, Fonts.
and Image.
. These are SwiftGen structs for UIColor
, UIFont
and UIImage
In my UINavigationController
subclass, I have
private func setupNavigationBar() {
self.navigation.configuration.isEnabled = true
self.navigation.configuration.titleTextAttributes = [
.foregroundColor: Colour.text
]
self.navigation.configuration.barTintColor = Colour.layer1
self.navigation.configuration.isTranslucent = false
self.navigation.configuration.isHidden = true
self.navigation.configuration.backItem = UINavigationController
.Configuration
.BackItem(style: .image(Image.back),
tintColor: Colour.text)
}
The homepage has
private fund setupNavigationBar() {
self.navigation.bar.isHidden = false
self.navigation.bar.prefersLargeTitles = false
self.navigation.item.largeTitleDisplayMode = .never
self.navigation.bar.additionalHeight = 20
// acts as a bit of a skirt to keep the label off the bottom of the nav bar
let navFooter = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 18))
navFooter.backgroundColor = Colour.layer1
self.navigation.bar.additionalView = navFooter
// title
let label = UILabel(frame: .zero)
label.text = "Explore"
label.font = Fonts.h2
self.navigation.item.leftBarButtonItem = UIBarButtonItem(customView: label)
// search button
let imageview = UIImageView()
imageview.image = Image.search.withRenderingMode(.alwaysTemplate)
imageview.tintColor = Colour.text
let searchButton = UIButton(type: .custom)
searchButton.addTarget(buttonTarget, action: buttonSelector, for: .touchUpInside)
searchButton.addSubview(imageview)
searchButton.accessibilityIdentifier = "nav_button"
// snapkit constraints
imageview.snp.makeConstraints { (make) in
make.width.height.equalTo(24)
make.left.right.equalToSuperview()
make.top.bottom.equalToSuperview().inset(10)
}
self.navigation.item.rightBarButtonItem = UIBarButtonItem(customView: searchButton)
}
Before the next view controller is pushed, I call
trendingViewController.navigationItem.title = "Trending"
then in viewDidLoad(animated:)
on that view controller, I call
self.navigation.bar.prefersLargeTitles = true
self.navigation.item.largeTitleDisplayMode = .always
Then, my UI tests goes something like this
let app = XCUIApplication()
// tap cell to get into view controller
// test element exists
app.navigationBars.buttons.element(boundBy: 0).tap() // <-- fails
Thanks
navigation.bar.backBarButtonItem = .init(style: .image(image))
Try using it in trendingViewController
Sadly not made any difference. Putting a breakpoint in my test, when I type into the console
po app.navigationBars.buttons
I get the following output
Find: Target Application 'com.my.app'
Output: {
Application, pid: 18209, label: 'App'
}
↪︎Find: Descendants matching type NavigationBar
Output: {
NavigationBar, {{0.0, 47.0}, {428.0, 96.0}}, identifier: 'Trending'
NavigationBar, {{0.0, 47.0}, {428.0, 96.0}}, identifier: 'Trending'
}
↪︎Find: Descendants matching type Button
Output: {
Button, {{0.0, 47.0}, {55.7, 44.0}}, label: 'Back'
Button, {{12.0, 47.0}, {36.0, 44.0}}
}
I'm sure you'll know better than me, but I think it a bit weird there are two buttons, one which says "Back". Either way, when doing either po app.navigationBars.buttons.element(boundBy: 0).isHittable
is false for both 0 and 1.
I'm not sure if that's helpful.