import XCTest /// Rebuild plan for legacy Suite2 failures: /// - test02_loginWithValidCredentials /// - test06_logout final class Suite2_AuthenticationRebuildTests: BaseUITestCase { override var includeResetStateLaunchArgument: Bool { false } override var relaunchBetweenTests: Bool { true } private let validUser = RebuildTestUserFactory.seeded private enum AuthLandingState { case main case verification } override func setUpWithError() throws { // Force a clean app launch so no stale field text persists between tests app.terminate() try super.setUpWithError() UITestHelpers.ensureLoggedOut(app: app) } private func loginFromLoginScreen(user: RebuildTestUser = RebuildTestUserFactory.seeded) { UITestHelpers.ensureOnLoginScreen(app: app) let login = LoginScreenObject(app: app) login.waitForLoad(timeout: defaultTimeout) login.enterUsername(user.username) login.enterPassword(user.password) let loginButton = app.buttons[AccessibilityIdentifiers.Authentication.loginButton] loginButton.waitForExistenceOrFail(timeout: defaultTimeout) loginButton.forceTap() } @discardableResult private func loginAndWaitForAuthenticatedLanding(user: RebuildTestUser = RebuildTestUserFactory.seeded) -> AuthLandingState { loginFromLoginScreen(user: user) let mainRoot = app.otherElements[UITestID.Root.mainTabs] if mainRoot.waitForExistence(timeout: loginTimeout) || app.tabBars.firstMatch.waitForExistence(timeout: 2) { return .main } let verification = VerificationScreen(app: app) if verification.codeField.waitForExistence(timeout: defaultTimeout) || verification.verifyButton.waitForExistence(timeout: 2) { return .verification } XCTFail("Expected authenticated landing on main tabs or verification screen") return .verification } private func logoutFromVerificationIfNeeded() { let verification = VerificationScreen(app: app) verification.waitForLoad(timeout: defaultTimeout) verification.tapLogoutIfAvailable() let toolbarLogout = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Logout' OR label CONTAINS[c] 'Log Out'")).firstMatch if toolbarLogout.waitForExistence(timeout: 3) { toolbarLogout.forceTap() } } private func logoutFromMainApp() { UITestHelpers.logout(app: app) } func testR201_loginScreenLoadsFromOnboardingEntry() { UITestHelpers.ensureOnLoginScreen(app: app) let login = LoginScreenObject(app: app) login.waitForLoad(timeout: defaultTimeout) } func testR202_validCredentialsSubmitFromLogin() { UITestHelpers.ensureOnLoginScreen(app: app) let login = LoginScreenObject(app: app) login.waitForLoad(timeout: defaultTimeout) login.enterUsername(validUser.username) login.enterPassword(validUser.password) let loginButton = app.buttons[AccessibilityIdentifiers.Authentication.loginButton] XCTAssertTrue(loginButton.waitForExistence(timeout: defaultTimeout), "Login button must exist before submit") XCTAssertTrue(loginButton.isHittable, "Login button must be tappable") } func testR203_validLoginTransitionsToMainAppRoot() { let landing = loginAndWaitForAuthenticatedLanding(user: validUser) switch landing { case .main: RebuildSessionAssertions.assertOnMainApp(app, timeout: loginTimeout) case .verification: RebuildSessionAssertions.assertOnVerification(app, timeout: loginTimeout) } } func testR204_mainAppHasExpectedPrimaryTabsAfterLogin() { let landing = loginAndWaitForAuthenticatedLanding(user: validUser) switch landing { case .main: RebuildSessionAssertions.assertOnMainApp(app, timeout: loginTimeout) let tabBar = app.tabBars.firstMatch if tabBar.waitForExistence(timeout: 5) { let residences = tabBar.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch let tasks = tabBar.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Tasks'")).firstMatch let contractors = tabBar.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Contractors'")).firstMatch let docs = tabBar.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Doc'")).firstMatch XCTAssertTrue(residences.exists, "Residences tab should exist") XCTAssertTrue(tasks.exists, "Tasks tab should exist") XCTAssertTrue(contractors.exists, "Contractors tab should exist") XCTAssertTrue(docs.exists, "Documents tab should exist") } else { XCTAssertTrue(app.otherElements[UITestID.Root.mainTabs].exists, "Main tabs root should exist") } case .verification: let verify = VerificationScreen(app: app) verify.waitForLoad(timeout: defaultTimeout) XCTAssertTrue(verify.codeField.exists, "Verification code field should exist for unverified accounts") } } func testR205_logoutFromMainAppReturnsToLoginRoot() { let landing = loginAndWaitForAuthenticatedLanding(user: validUser) switch landing { case .main: logoutFromMainApp() case .verification: logoutFromVerificationIfNeeded() } RebuildSessionAssertions.assertOnLogin(app, timeout: loginTimeout) } func testR206_postLogoutMainAppIsNoLongerAccessible() { let landing = loginAndWaitForAuthenticatedLanding(user: validUser) switch landing { case .main: logoutFromMainApp() case .verification: logoutFromVerificationIfNeeded() } RebuildSessionAssertions.assertOnLogin(app, timeout: loginTimeout) XCTAssertFalse(app.otherElements[UITestID.Root.mainTabs].exists, "Main app root should not be visible after logout") } }