- Add 8 new test files: HeaderMoodLogging (TC-002), DayViewGrouping (TC-019), AllDayViewStyles (TC-021), MonthViewInteraction (TC-030), PaywallGate (TC-032/039/048), AppTheme (TC-070), IconPack (TC-072), PremiumCustomization (TC-075) - Add accessibility IDs for paywall overlays, icon packs, app theme cards, and day view section headers - Add --expire-trial launch argument to UITestMode for paywall gate testing - Update QA test plan spreadsheet with XCUITest names for 14 test cases - Include existing test infrastructure: screen objects, helpers, base class, and 19 previously written test files Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
66 lines
2.4 KiB
Swift
66 lines
2.4 KiB
Swift
//
|
|
// WaitHelpers.swift
|
|
// Tests iOS
|
|
//
|
|
// Centralized, explicit wait helpers. No sleep() allowed.
|
|
//
|
|
|
|
import XCTest
|
|
|
|
extension XCUIElement {
|
|
|
|
/// Wait for the element to exist in the hierarchy.
|
|
/// - Parameters:
|
|
/// - timeout: Maximum seconds to wait.
|
|
/// - message: Custom failure message.
|
|
/// - Returns: `true` if the element exists within the timeout.
|
|
@discardableResult
|
|
func waitForExistence(timeout: TimeInterval = 5, message: String? = nil) -> Bool {
|
|
let result = waitForExistence(timeout: timeout)
|
|
if !result, let message = message {
|
|
XCTFail(message)
|
|
}
|
|
return result
|
|
}
|
|
|
|
/// Wait until the element is hittable (exists and is enabled/visible).
|
|
/// - Parameter timeout: Maximum seconds to wait.
|
|
@discardableResult
|
|
func waitUntilHittable(timeout: TimeInterval = 5) -> Bool {
|
|
let predicate = NSPredicate(format: "isHittable == true")
|
|
let expectation = XCTNSPredicateExpectation(predicate: predicate, object: self)
|
|
let result = XCTWaiter.wait(for: [expectation], timeout: timeout)
|
|
return result == .completed
|
|
}
|
|
|
|
/// Tap the element after waiting for it to become hittable.
|
|
/// - Parameter timeout: Maximum seconds to wait before tapping.
|
|
func tapWhenReady(timeout: TimeInterval = 5, file: StaticString = #file, line: UInt = #line) {
|
|
guard waitUntilHittable(timeout: timeout) else {
|
|
XCTFail("Element \(identifier) not hittable after \(timeout)s", file: file, line: line)
|
|
return
|
|
}
|
|
tap()
|
|
}
|
|
|
|
/// Wait for the element to disappear from the hierarchy.
|
|
/// - Parameter timeout: Maximum seconds to wait.
|
|
@discardableResult
|
|
func waitForDisappearance(timeout: TimeInterval = 5) -> Bool {
|
|
let predicate = NSPredicate(format: "exists == false")
|
|
let expectation = XCTNSPredicateExpectation(predicate: predicate, object: self)
|
|
let result = XCTWaiter.wait(for: [expectation], timeout: timeout)
|
|
return result == .completed
|
|
}
|
|
}
|
|
|
|
extension XCUIApplication {
|
|
|
|
/// Wait for any element matching the identifier to exist.
|
|
func waitForElement(identifier: String, timeout: TimeInterval = 5) -> XCUIElement {
|
|
let element = descendants(matching: .any).matching(identifier: identifier).firstMatch
|
|
_ = element.waitForExistence(timeout: timeout)
|
|
return element
|
|
}
|
|
}
|