import XCTest /// Reusable helper functions for UI tests struct UITestHelpers { // MARK: - Authentication Helpers /// Logs out the user if they are currently logged in /// - Parameter app: The XCUIApplication instance static func logout(app: XCUIApplication) { sleep(2) // Check if already logged out (login screen visible) let welcomeText = app.staticTexts["Welcome Back"] if welcomeText.exists { // Already logged out return } // Check if we have a tab bar (logged in state) let tabBar = app.tabBars.firstMatch guard tabBar.exists else { return } // Navigate to Residences tab first let residencesTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch if residencesTab.exists { residencesTab.tap() sleep(1) } // Tap settings button let settingsButton = app.buttons[AccessibilityIdentifiers.Navigation.settingsButton] if settingsButton.waitForExistence(timeout: 3) && settingsButton.isHittable { settingsButton.tap() sleep(1) } // Find and tap logout button let logoutButton = app.buttons[AccessibilityIdentifiers.Profile.logoutButton] if logoutButton.waitForExistence(timeout: 3) { logoutButton.tap() sleep(1) // Confirm logout in alert if present - specifically target the alert's button let alert = app.alerts.firstMatch if alert.waitForExistence(timeout: 2) { let confirmLogout = alert.buttons["Log Out"] if confirmLogout.exists { confirmLogout.tap() } } } sleep(2) // Verify we're back on login screen XCTAssertTrue(welcomeText.waitForExistence(timeout: 5), "Failed to log out - Welcome Back screen should appear after logout") } /// Logs in a user with the provided credentials /// - Parameters: /// - app: The XCUIApplication instance /// - username: The username/email to use for login /// - password: The password to use for login static func login(app: XCUIApplication, username: String, password: String) { // Find username field by accessibility identifier let usernameField = app.textFields[AccessibilityIdentifiers.Authentication.usernameField] XCTAssertTrue(usernameField.waitForExistence(timeout: 5), "Username field should exist") usernameField.tap() usernameField.typeText(username) // Find password field - it could be TextField (if visible) or SecureField var passwordField = app.secureTextFields[AccessibilityIdentifiers.Authentication.passwordField] if !passwordField.exists { passwordField = app.textFields[AccessibilityIdentifiers.Authentication.passwordField] } XCTAssertTrue(passwordField.waitForExistence(timeout: 3), "Password field should exist") passwordField.tap() passwordField.typeText(password) // Find and tap login button let loginButton = app.buttons[AccessibilityIdentifiers.Authentication.loginButton] XCTAssertTrue(loginButton.waitForExistence(timeout: 3), "Login button should exist") loginButton.tap() // Wait for login to complete sleep(3) } /// Ensures the user is logged out before running a test /// - Parameter app: The XCUIApplication instance static func ensureLoggedOut(app: XCUIApplication) { sleep(2) logout(app: app) } /// Ensures the user is logged in with test credentials before running a test /// - Parameter app: The XCUIApplication instance /// - Parameter username: Optional username (defaults to "testuser") /// - Parameter password: Optional password (defaults to "TestPass123!") static func ensureLoggedIn(app: XCUIApplication, username: String = "testuser", password: String = "TestPass123!") { sleep(2) // Check if already logged in (tab bar visible) let tabBar = app.tabBars.firstMatch if tabBar.exists { return // Already logged in } // Check if on login screen let usernameField = app.textFields[AccessibilityIdentifiers.Authentication.usernameField] if usernameField.waitForExistence(timeout: 5) { login(app: app, username: username, password: password) // Wait for main screen to appear _ = tabBar.waitForExistence(timeout: 10) } } }