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 } // User is logged in, need to log them out let profileTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Profile'")).firstMatch if profileTab.exists { profileTab.tap() sleep(1) let logoutButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Logout' OR label CONTAINS[c] 'Log Out' OR label CONTAINS[c] 'Sign Out'")).firstMatch if logoutButton.waitForExistence(timeout: 5) { logoutButton.tap() sleep(1) // Tap the "Log Out" button on the alert let alertLogoutButton = app.alerts.buttons["Log Out"] if alertLogoutButton.exists { alertLogoutButton.tap() sleep(2) } else { // Fallback to broader search if exact match not found let confirmButton = app.alerts.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Logout' OR label CONTAINS[c] 'Log Out' OR label CONTAINS[c] 'Confirm' OR label CONTAINS[c] 'Yes'")).firstMatch if confirmButton.exists { confirmButton.tap() sleep(2) } } } } // if user is on verify screen after previous test let logoutButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Logout'")).firstMatch if logoutButton.exists { logoutButton.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) { let usernameField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'email'")).firstMatch XCTAssertTrue(usernameField.waitForExistence(timeout: 5), "Username field should exist") usernameField.tap() usernameField.typeText(username) let passwordField = app.secureTextFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'password'")).firstMatch XCTAssertTrue(passwordField.exists, "Password field should exist") passwordField.tap() passwordField.typeText(password) let signInButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Sign In'")).firstMatch XCTAssertTrue(signInButton.exists, "Sign In button should exist") signInButton.tap() } /// Ensures the user is logged out before running a test /// - Parameter app: The XCUIApplication instance static func ensureLoggedOut(app: XCUIApplication) { sleep(3) 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(3) // Need to login let usernameField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'email'")).firstMatch if usernameField.waitForExistence(timeout: 5) { login(app: app, username: username, password: password) // Wait for main screen to appear let mainTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences' OR label CONTAINS[c] 'Tasks'")).firstMatch _ = mainTab.waitForExistence(timeout: 10) } else { return } } }