'How to locate element on system action sheet in iOS UI Test
Our app will pop up a system action sheet on the bottom of iPhone screen as below screenshots illustrated. I want to locate and tap the "Call..." and "Cancel" button on that action sheet in UI Test.
First, I tried to add an UI interruption handler, and put a break point into the handler closure but it is not triggered when action sheet showed.
// Add an UI interruption handler to handle system alert.
addUIInterruptionMonitor(withDescription: "Notification permisson request") { alert in
let notifyAllowBtn = alert.buttons["Allow"]
let callBtn = alert.buttons["Call 8663xxxxx"]
if notifyAllowBtn.exists {
notifyAllowBtn.tap()
return true
}
if callBtn.exists {
callBtn.tap()
return true
}
// A placeholder for other alerts
return true
}
// need to interact with the app again for the handler to fire
app.swipeUp()
Also I have another try with SpringBoard, still without luck. Need help here, how could I locate the element on system action sheet?
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let alertCallButton = springboard.buttons["Call 8663xxxxx"]
XCTAssert(alertCallButton.waitForExistence(timeout: 5))
Solution 1:[1]
As @stackich said, I add a 30 seconds delay to find elements on Springboard. And it works. I put my test in below in case anyone meet the same problem in the future.
Worth to mention that, for our app it is not Action sheet actually, instead it is text associated with UITextView, and UITextViewDelegate method textView(_ textView: UITextView, shouldInteractWith URL:... is fired when a user click a URL.
UI Test, the call button is actually a staticText/Label. The cancel button is button. So be sure to give them the correct type.
func testPhoneCall() {
app = XCUIApplication()
springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
app.launch()
app.links["888-111-2222"].tap()
sleep(1)
let callLabel = springboard.staticTexts["Call (888) 111 2222"]
print(" ? \(springboard.debugDescription)")
// Add a 30 seconds waiting for springboard available
XCTAssert(callLabel.waitForExistence(timeout: 30))
// callLabel.tap()
}
Minimum test app
import UIKit
class ViewController: UIViewController, UITextViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "Main View"
addUITextViews()
}
func addUITextViews(){
// lauout for the View
let myTextView3 = UITextView()
myTextView3.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(myTextView3)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
myTextView3.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40),
myTextView3.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 40),
myTextView3.centerXAnchor.constraint(equalTo: view.centerXAnchor),
myTextView3.centerYAnchor.constraint(equalTo: view.centerYAnchor),
myTextView3.widthAnchor.constraint(equalToConstant: 400),
myTextView3.heightAnchor.constraint(equalToConstant: 400),
])
// set Phone# and Email Address for the UITextView
myTextView3.font = UIFont.systemFont(ofSize: 24)
myTextView3.isEditable = false
myTextView3.isSelectable = true
myTextView3.text = "Phone: 888-111-2222 \nEmail: [email protected]"
myTextView3.dataDetectorTypes = .all
myTextView3.delegate = self
}
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
guard let currentScheme = URL.scheme else { return false }
switch currentScheme {
case "sms", "tel":
print("It is a call!")
case "mailto":
print("send email")
default: break
}
return true
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | ChuckZHB |

