import XCTest /// Helper extensions and utilities for UI tests extension XCUIApplication { /// Launch the app and reset to initial state func launchAndReset() { launchArguments = ["--uitesting"] launch() } /// Clear all text from a text field func clearText(in textField: XCUIElement) { textField.tap() textField.press(forDuration: 1.2) menuItems["Select All"].tap() textField.typeText(XCUIKeyboardKey.delete.rawValue) } } /// Base test class with common setup and teardown class BaseUITest: XCTestCase { var app: XCUIApplication! override func setUp() { super.setUp() continueAfterFailure = false app = XCUIApplication() app.launchAndReset() } override func tearDown() { app = nil super.tearDown() } // MARK: - Authentication Helpers func login(username: String, password: String) { let usernameField = app.textFields["Username"] let passwordField = app.secureTextFields["Password"] let loginButton = app.buttons["Login"] if usernameField.exists { usernameField.tap() usernameField.typeText(username) } if passwordField.exists { passwordField.tap() passwordField.typeText(password) } if loginButton.exists { loginButton.tap() } } func logout() { let profileTab = app.tabBars.buttons["Profile"] profileTab.tap() let logoutButton = app.buttons["Log Out"] XCTAssertTrue(logoutButton.waitForExistence(timeout: 5)) logoutButton.tap() } func register(username: String, email: String, password: String, firstName: String = "", lastName: String = "") { let signUpButton = app.buttons["Sign Up"] XCTAssertTrue(signUpButton.waitForExistence(timeout: 3)) signUpButton.tap() let usernameField = app.textFields["Username"] let emailField = app.textFields["Email"] let passwordField = app.secureTextFields["Password"] let registerButton = app.buttons["Register"] usernameField.tap() usernameField.typeText(username) emailField.tap() emailField.typeText(email) passwordField.tap() passwordField.typeText(password) if !firstName.isEmpty { let firstNameField = app.textFields["First Name"] firstNameField.tap() firstNameField.typeText(firstName) } if !lastName.isEmpty { let lastNameField = app.textFields["Last Name"] lastNameField.tap() lastNameField.typeText(lastName) } registerButton.tap() } // MARK: - Navigation Helpers func navigateToTab(_ tabName: String) { let tab = app.tabBars.buttons[tabName] XCTAssertTrue(tab.waitForExistence(timeout: 3)) tab.tap() } func navigateBack() { app.navigationBars.buttons.element(boundBy: 0).tap() } // MARK: - Assertion Helpers func assertElementExists(_ identifier: String, timeout: TimeInterval = 5) { let element = app.descendants(matching: .any).matching(identifier: identifier).firstMatch XCTAssertTrue(element.waitForExistence(timeout: timeout), "Element '\(identifier)' does not exist") } func assertElementDoesNotExist(_ identifier: String, timeout: TimeInterval = 2) { let element = app.descendants(matching: .any).matching(identifier: identifier).firstMatch XCTAssertFalse(element.waitForExistence(timeout: timeout), "Element '\(identifier)' should not exist") } func assertNavigatedTo(title: String, timeout: TimeInterval = 5) { let navigationBar = app.navigationBars[title] XCTAssertTrue(navigationBar.waitForExistence(timeout: timeout), "Did not navigate to '\(title)'") } // MARK: - Wait Helpers func wait(seconds: TimeInterval) { Thread.sleep(forTimeInterval: seconds) } func waitForElementToAppear(_ element: XCUIElement, timeout: TimeInterval = 5) -> Bool { return element.waitForExistence(timeout: timeout) } func waitForElementToDisappear(_ element: XCUIElement, timeout: TimeInterval = 5) -> Bool { let predicate = NSPredicate(format: "exists == false") let expectation = XCTNSPredicateExpectation(predicate: predicate, object: element) let result = XCTWaiter.wait(for: [expectation], timeout: timeout) return result == .completed } } /// Identifiers for UI elements (for better testability) struct Identifiers { struct Authentication { static let usernameField = "UsernameField" static let passwordField = "PasswordField" static let loginButton = "LoginButton" static let registerButton = "RegisterButton" static let logoutButton = "LogoutButton" } struct Residence { static let addButton = "AddResidenceButton" static let editButton = "EditResidenceButton" static let deleteButton = "DeleteResidenceButton" static let nameField = "ResidenceNameField" static let addressField = "ResidenceAddressField" } struct Task { static let addButton = "AddTaskButton" static let completeButton = "CompleteTaskButton" static let editButton = "EditTaskButton" static let titleField = "TaskTitleField" static let descriptionField = "TaskDescriptionField" } struct MultiUser { static let manageUsersButton = "ManageUsersButton" static let generateCodeButton = "GenerateCodeButton" static let joinButton = "JoinResidenceButton" static let shareCodeField = "ShareCodeField" } }