// // TestHelpers.swift // iOS Foundations // // Common test utilities and helpers // import XCTest /// Common test helper functions public enum TestHelpers { // MARK: - Async Testing /// Wait for an async condition to become true /// /// - Parameters: /// - timeout: Maximum time to wait /// - condition: The condition to check /// /// - Returns: true if condition became true within timeout /// @discardableResult public static func wait( timeout: TimeInterval = 5.0, for condition: @escaping () -> Bool ) -> Bool { let expectation = XCTNSPredicateExpectation( predicate: NSPredicate(block: { _, _ in condition() }), object: nil ) let result = XCTWaiter().wait(for: [expectation], timeout: timeout) return result == .completed } /// Wait for an async operation with timeout /// /// - Parameters: /// - timeout: Maximum time to wait /// - operation: The async operation to perform /// public static func waitForAsync( timeout: TimeInterval = 5.0, operation: @escaping (@escaping () -> Void) -> Void ) async { await withCheckedContinuation { continuation in let timeoutTimer = Timer.scheduledTimer(withTimeInterval: timeout, repeats: false) { _ in continuation.resume() } operation { timeoutTimer.invalidate() continuation.resume() } } } // MARK: - Data Generation /// Generate a random string /// /// - Parameter length: Length of the string /// - Returns: Random alphanumeric string /// public static func randomString(length: Int) -> String { let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" return String((0.. String { "\(randomString(length: 10))@test.com" } // MARK: - File Helpers /// Get path to a test resource file /// /// - Parameters: /// - name: File name /// - extension: File extension /// - bundle: Bundle containing the file (defaults to test bundle) /// /// - Returns: Path to the file, or nil if not found /// public static func pathForTestResource( named name: String, withExtension extension: String, in bundle: Bundle = Bundle(for: BundleToken.self) ) -> String? { bundle.path(forResource: name, ofType: `extension`) } } /// Token class for bundle identification public class BundleToken {}