Looking at XCTWaiter().wait(...) I believe we can wait for multiple expectations to become true using this code
let notHittablePredicate = NSPredicate(format: "hittable == false")
let myExpectation = XCTNSPredicateExpectation(predicate: notHittablePredicate, object: element)
let result = XCTWaiter().wait(for: [myExpectation], timeout: timeout)
//for takes array of expectations
But this uses like AND among the supplied expectations. Is there a way to do OR among the supplied expectations.
Like i have a use case at login that after tapping submit, i want to wait for one of two elements. First element is "You are already logged in on another device. If you continue any unsaved data on your other device will be lost?". And second element is the main screen after login. So any one can appear. Currently I'm first waiting for first element until timeout occurs and then for the second element. But I want to optimize time here and move on as soon as any of two elements exist==true. Then i'll check if element1 exists then tap YES and then wait for main screen otherwise just assert existence of element2.
Please comment if something isn't clear in the question. Thanks
Inspired by http://masilotti.com/ui-testing-tdd/, you don't have to rely on XCTWaiter
. You can simply run a loop and test whether one of them exists.
/// Waits for either of the two elements to exist (i.e. for scenarios where you might have
/// conditional UI logic and aren't sure which will show)
///
/// - Parameters:
/// - elementA: The first element to check for
/// - elementB: The second, or fallback, element to check for
/// - Returns: the element that existed
@discardableResult
func waitForEitherElementToExist(_ elementA: XCUIElement, _ elementB: XCUIElement) -> XCUIElement? {
let startTime = NSDate.timeIntervalSinceReferenceDate
while (!elementA.exists && !elementB.exists) { // while neither element exists
if (NSDate.timeIntervalSinceReferenceDate - startTime > 5.0) {
XCTFail("Timed out waiting for either element to exist.")
break
}
sleep(1)
}
if elementA.exists { return elementA }
if elementB.exists { return elementB }
return nil
}
then you could just do:
let foundElement = waitForEitherElementToExist(elementA, elementB)
if foundElement == elementA {
// e.g. if it's a button, tap it
} else {
// element B was found
}