Wait until object is not visible on the screen using Swift and XCTest
Asked Answered
G

4

10

I'm looking for help writing a method which waits until the specified element is not present on a page anymore. I am developing with Swift 2.2 and XCTest. As you can see, I'm a new here and new to programming. Your help will be greatly appreciated.

Gouache answered 25/5, 2016 at 20:31 Comment(0)
F
20

You will have to setup predicate for the condition you want to test:

let doesNotExistPredicate = NSPredicate(format: "exists == FALSE")

Then create an expectation for your predicate and UI element in your test case:

self.expectationForPredicate(doesNotExistPredicate, evaluatedWithObject: element, handler: nil)

Then wait for your expectation (specifying a timeout after which the test will fail if the expectation is not met, here I use 5 seconds):

self.waitForExpectationsWithTimeout(5.0, handler: nil)
Fogarty answered 25/5, 2016 at 20:35 Comment(1)
From all solutions I've seen online, this one that uses expectationForPredicate has been the only one that works correctly with XCUITest. Avoid using XCTNSPredicateExpectation or XCWaiter as those tend to just run the whole timeout period and not exit early when the element is already not existentCatalinacatalo
L
7

I wrote a super simple waitForNonExistence(timeout:) extension function on XCUIElement for this which mirrors the existing XCUIElement.waitForExistence(timeout:) function, as follows:

extension XCUIElement {

    /**
     * Waits the specified amount of time for the element’s `exists` property to become `false`.
     *
     * - Parameter timeout: The amount of time to wait.
     * - Returns: `false` if the timeout expires without the element coming out of existence.
     */
    func waitForNonExistence(timeout: TimeInterval) -> Bool {
    
        let timeStart = Date().timeIntervalSince1970
    
        while (Date().timeIntervalSince1970 <= (timeStart + timeout)) {
            if !exists { return true }
        }
    
        return false
    }
}
Lohse answered 25/7, 2020 at 14:53 Comment(0)
S
1

You can check the element by XCUIElement.exists for 10 second for each second and then assert the element. See the following for ActivityIndicator:

public func waitActivityIndicator() {
    var numberTry = 0
    var activityIndicatorNotVisible = false
    while numberTry < 10 {
        if activityIdentifier.exists {
            sleep(1)
            numberTry += 1
        } else {
            activityIndicatorNotVisible = true
            break
        }
    }
    
    XCTAssert(activityIndicatorNotVisible, "Activity indicator is still visible")
}
Symphysis answered 18/11, 2020 at 15:19 Comment(0)
C
1

@Charles A has the correct answer. Below is the Swift 5 version of the same.

        let doesNotExistPredicate = NSPredicate(format: "exists == FALSE")
    expectation(for: doesNotExistPredicate, evaluatedWith: element, handler: nil)
    waitForExpectations(timeout: 5.0, handler: nil)
Chalet answered 4/4, 2022 at 6:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.