import XCTest /// Reusable helper functions for UI tests. /// All waits use explicit conditions — zero sleep() calls. struct UITestHelpers { // MARK: - Authentication Helpers /// Logs out the user if they are currently logged in. static func logout(app: XCUIApplication) { // Check if already logged out (login screen visible) let welcomeText = app.staticTexts["Welcome Back"] if welcomeText.waitForExistence(timeout: 3) { return } // Check if we have a tab bar (logged in state) let tabBar = app.tabBars.firstMatch guard tabBar.waitForExistence(timeout: 3) else { return } // Navigate to Residences tab first let residencesTab = app.tabBars.buttons[AccessibilityIdentifiers.Navigation.residencesTab] if residencesTab.exists { residencesTab.tap() } // Tap settings button let settingsButton = app.buttons[AccessibilityIdentifiers.Navigation.settingsButton] if settingsButton.waitForExistence(timeout: 5) { settingsButton.tap() } // Find and tap logout button let logoutButton = app.buttons[AccessibilityIdentifiers.Profile.logoutButton] if logoutButton.waitForExistence(timeout: 5) { logoutButton.tap() // Confirm logout in alert if present let alert = app.alerts.firstMatch if alert.waitForExistence(timeout: 3) { let confirmLogout = alert.buttons["Log Out"] if confirmLogout.exists { confirmLogout.tap() } } } // Verify we're back on login screen XCTAssertTrue( welcomeText.waitForExistence(timeout: 10), "Failed to log out - Welcome Back screen should appear after logout" ) } /// Logs in a user with the provided credentials. static func login(app: XCUIApplication, username: String, password: String) { let usernameField = app.textFields[AccessibilityIdentifiers.Authentication.usernameField] XCTAssertTrue(usernameField.waitForExistence(timeout: 5), "Username field should exist") usernameField.tap() usernameField.typeText(username) // Password field may be SecureTextField or regular TextField 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) let loginButton = app.buttons[AccessibilityIdentifiers.Authentication.loginButton] XCTAssertTrue(loginButton.waitForExistence(timeout: 3), "Login button should exist") loginButton.tap() // Wait for login to complete by checking for tab bar appearance let tabBar = app.tabBars.firstMatch _ = tabBar.waitForExistence(timeout: 15) } /// Ensures the user is logged out before running a test. static func ensureLoggedOut(app: XCUIApplication) { logout(app: app) } /// Ensures the user is logged in with test credentials before running a test. static func ensureLoggedIn( app: XCUIApplication, username: String = "testuser", password: String = "TestPass123!" ) { // Check if already logged in (tab bar visible) let tabBar = app.tabBars.firstMatch if tabBar.waitForExistence(timeout: 5) { return } // Check if on login screen let usernameField = app.textFields[AccessibilityIdentifiers.Authentication.usernameField] if usernameField.waitForExistence(timeout: 5) { login(app: app, username: username, password: password) _ = tabBar.waitForExistence(timeout: 15) } } }