This is how I simply create UIAlertController
and present it on the screen:
private class func showAlertWithTitle(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
//alert.accessibilityLabel = "my string here" //doesnt work
let action = UIAlertAction(title: "OK", style: .Default) { action in
alert.dismissViewControllerAnimated(true, completion: nil)
}
alert.addAction(action)
UIStoryboard.topViewController()?.presentViewController(alert, animated: true, completion: nil)
}
and this is how I access it under UITests:
emailAlert = app.alerts["First Name"] //for title "First Name"
but I would like to set there custom identifier and access this by firstName
like this:
emailAlert = app.alerts["firstName"]
Is it possible?
This is an old thread but someone might use this.
I was able to set the accessibility identifier like this:
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) alert.view.accessibilityIdentifier = "custom_alert" alert.view.accessibilityValue = "\(title)-\(message)" alert.addAction( UIAlertAction( title: "ALERT_BUTTON_OK".localized, style: .default, handler: handler ) ) present(alert, animated: true)
That way I can access the alert by accessibility identifier and check its contents in accessibility value.
It is not perfect of course, but it works - at least for my testing using Appium.
The only way I figured out to do this was to use Apple's private APIs. You call valueForKey
on the UIAlertAction
object with this super secret key: "__representer"
to get whats called a _UIAlertControllerActionView
.
let alertView = UIAlertController(title: "This is Alert!", message: "This is a message!", preferredStyle: .Alert) let okAction = UIAlertAction(title: "OK", style: .Default, handler: nil) alertView.addAction(okAction) self.presentViewController(alertView, animated: true, completion: { let alertButton = action.valueForKey("__representer") let view = alertButton as? UIView view?.accessibilityIdentifier = "okAction_AID" })
This has to be done in the completion handler because that that _UIAlertControllerActionView
won't exist until the view is presented. On a side note in my project I used these following extensions to make things easier / more readable:
extension UIAlertController { func applyAccessibilityIdentifiers() { for action in actions { let label = action.valueForKey("__representer") let view = label as? UIView view?.accessibilityIdentifier = action.getAcAccessibilityIdentifier() } } } extension UIAlertAction { private struct AssociatedKeys { static var AccessabilityIdentifier = "nsh_AccesabilityIdentifier" } func setAccessibilityIdentifier(accessabilityIdentifier: String) { objc_setAssociatedObject(self, &AssociatedKeys.AccessabilityIdentifier, accessabilityIdentifier, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) } func getAcAccessibilityIdentifier() -> String? { return objc_getAssociatedObject(self, &AssociatedKeys.AccessabilityIdentifier) as? String } }
So the above code would be rewritten:
let alertView = UIAlertController(title: NSLocalizedString("NMN_LOGINPAGECONTROLLER_ERROR_TITLE", comment: ""), message: message as String, preferredStyle:.Alert) let okAction = UIAlertAction(title: NSLocalizedString("NMN_OK", comment: ""), style: .Default, handler: nil) okAction.setAccessibilityIdentifier(InvalidLoginAlertView_AID) alertView.addAction(okAction) self.presentViewController(alertView, animated: true, completion: { alertView.applyAccessibilityIdentifiers() })
My first attempt involved trying to navigate the view hierarchy but that became difficult since UIAlertControllerActionView
was not a part of the public API. Anyway I'd probably would try to ifdef out the valueForKey("__representer")
for builds submitted for the app store or Apple might give you a spanking.
Right now I have a UIAlertAction
called addCamera
and I'm just doing:
addCamera.accessibilityLabel = "camera-autocomplete-action-photo"
That allows me to tap it in UI Tests as follows:
app.sheets.buttons["camera-autocomplete-action-photo"].firstMatch.tap()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With