I want to have a test pause and wait for an element to appear on screen before proceeding.
I don't see a good way to create an expectation for this and wait using
public func waitForExpectationsWithTimeout(timeout: NSTimeInterval, handler: XCWaitCompletionHandler?)
The method to create an expectation I have been using has been
public func expectationForPredicate(predicate: NSPredicate, evaluatedWithObject object: AnyObject, handler: XCPredicateExpectationHandler?) -> XCTestExpectation
But this takes an already existing element, whereas I would like to have the test wait for an element that does not yet exist.
Does anyone know the best way to do this?
In expectationForPredicate(predicate: evaluatedWithObject: handler:)
you don't give an actual object, but a query to find it in the view hierarchy. So, for example, this is a valid test:
let predicate = NSPredicate(format: "exists == 1")
let query = XCUIApplication().buttons["Button"]
expectationForPredicate(predicate, evaluatedWithObject: query, handler: nil)
waitForExpectationsWithTimeout(3, handler: nil)
Check out UI Testing Cheat Sheet and documentation generated from the headers (there is no official documentation at the moment), all by Joe Masilotti.
This question was asked about Swift2 but it's still a top search result in 2019 so I wanted to give an up-to-date answer.
With Xcode 9.0+ things are a bit simpler thanks to waitForExistence
:
let app = XCUIApplication()
let myButton = app.buttons["My Button"]
XCTAssertTrue(myButton.waitForExistence(timeout: 10))
sleep(1)
myButton.tap()
WebViews Example:
let app = XCUIApplication()
let webViewsQuery = app.webViews
let myButton = webViewsQuery.staticTexts["My Button"]
XCTAssertTrue(myButton.waitForExistence(timeout: 10))
sleep(1)
myButton.tap()
You can use this, in Swift 3
func wait(element: XCUIElement, duration: TimeInterval) {
let predicate = NSPredicate(format: "exists == true")
let _ = expectation(for: predicate, evaluatedWith: element, handler: nil)
// We use a buffer here to avoid flakiness with Timer on CI
waitForExpectations(timeout: duration + 0.5)
}
In Xcode 9, iOS 11, you can use the new API waitForExistence
It doesn't take an already existing element. You just need to define the following predicate:
let exists = NSPredicate(format: "exists = 1")
Then just use this predicate in your expectation. Then of course wait on your expectation.
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