import XCTest /// Critical path tests for authentication flows. /// /// Validates login, logout, registration entry, and password reset entry. /// Zero sleep() calls — all waits are condition-based. final class AuthCriticalPathTests: XCTestCase { var app: XCUIApplication! override func setUp() { super.setUp() continueAfterFailure = false addUIInterruptionMonitor(withDescription: "System Alert") { alert in let buttons = ["Allow", "OK", "Don't Allow", "Not Now", "Dismiss", "Allow While Using App"] for label in buttons { let button = alert.buttons[label] if button.exists { button.tap() return true } } return false } app = TestLaunchConfig.launchApp() } override func tearDown() { app = nil super.tearDown() } // MARK: - Helpers /// Navigate to the login screen, handling onboarding welcome if present. private func navigateToLogin() -> LoginScreen { let login = LoginScreen(app: app) // Already on login screen if login.emailField.waitForExistence(timeout: 5) { return login } // On onboarding welcome — tap "Already have an account?" to reach login let onboardingLogin = app.descendants(matching: .any) .matching(identifier: UITestID.Onboarding.loginButton).firstMatch if onboardingLogin.waitForExistence(timeout: 10) { if onboardingLogin.isHittable { onboardingLogin.tap() } else { onboardingLogin.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap() } _ = login.emailField.waitForExistence(timeout: 10) } return login } // MARK: - Login func testLoginWithValidCredentials() { let login = navigateToLogin() guard login.emailField.exists else { // Already logged in — verify main screen let main = MainTabScreen(app: app) XCTAssertTrue(main.isDisplayed, "Main screen should be visible when already logged in") return } let user = TestFixtures.TestUser.existing login.login(email: user.email, password: user.password) let main = MainTabScreen(app: app) let reached = main.residencesTab.waitForExistence(timeout: 15) || app.tabBars.firstMatch.waitForExistence(timeout: 3) if !reached { // Dump view hierarchy for diagnosis XCTFail("Should navigate to main screen after login. App state:\n\(app.debugDescription)") return } } func testLoginWithInvalidCredentials() { let login = navigateToLogin() guard login.emailField.exists else { return // Already logged in, skip } login.login(email: "invaliduser", password: "wrongpassword") // Should stay on login screen — email field should still exist XCTAssertTrue( login.emailField.waitForExistence(timeout: 10), "Should remain on login screen after invalid credentials" ) // Tab bar should NOT appear let tabBar = app.tabBars.firstMatch XCTAssertFalse(tabBar.exists, "Tab bar should not appear after failed login") } // MARK: - Logout func testLogoutFlow() { let login = navigateToLogin() if login.emailField.exists { let user = TestFixtures.TestUser.existing login.login(email: user.email, password: user.password) } let main = MainTabScreen(app: app) guard main.residencesTab.waitForExistence(timeout: 15) else { XCTFail("Main screen did not appear — app may be on onboarding or verification") return } main.logout() // Should be back on login screen or onboarding let loginAfterLogout = LoginScreen(app: app) let reachedLogin = loginAfterLogout.emailField.waitForExistence(timeout: 30) || app.otherElements["ui.root.login"].waitForExistence(timeout: 5) if !reachedLogin { // Check if we landed on onboarding instead let onboardingLogin = app.descendants(matching: .any) .matching(identifier: UITestID.Onboarding.loginButton).firstMatch if onboardingLogin.waitForExistence(timeout: 5) { // Onboarding is acceptable — logout succeeded return } XCTFail("Should return to login or onboarding screen after logout. App state:\n\(app.debugDescription)") } } // MARK: - Registration Entry func testSignUpButtonNavigatesToRegistration() { let login = navigateToLogin() guard login.emailField.exists else { return // Already logged in, skip } let register = login.tapSignUp() XCTAssertTrue(register.isDisplayed, "Registration screen should appear after tapping Sign Up") } // MARK: - Forgot Password Entry func testForgotPasswordButtonExists() { let login = navigateToLogin() guard login.emailField.exists else { return // Already logged in, skip } XCTAssertTrue( login.forgotPasswordButton.waitForExistence(timeout: 5), "Forgot password button should exist on login screen" ) } }