import XCTest /// Rebuild plan for legacy Suite3 failures (all blocked at residences tab precondition). /// Old tests covered: /// - test01_viewResidencesList /// - test02_navigateToAddResidence /// - test03_navigationBetweenTabs /// - test04_cancelResidenceCreation /// - test05_createResidenceWithMinimalData /// - test06_viewResidenceDetails final class Suite3_ResidenceRebuildTests: BaseUITestCase { override var includeResetStateLaunchArgument: Bool { false } override var relaunchBetweenTests: Bool { true } 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 loginAndOpenResidences() { UITestHelpers.ensureOnLoginScreen(app: app) let login = LoginScreenObject(app: app) login.waitForLoad(timeout: defaultTimeout) login.enterUsername("testuser") login.enterPassword("TestPass123!") app.buttons[AccessibilityIdentifiers.Authentication.loginButton].waitForExistenceOrFail(timeout: defaultTimeout).forceTap() // Wait for either main tabs or verification screen let main = MainTabScreenObject(app: app) let mainTabs = app.otherElements[UITestID.Root.mainTabs] let tabBar = app.tabBars.firstMatch let verificationScreen = VerificationScreen(app: app) let deadline = Date().addingTimeInterval(loginTimeout) while Date() < deadline { if mainTabs.exists || tabBar.exists { break } if verificationScreen.codeField.exists { verificationScreen.enterCode(TestAccountAPIClient.debugVerificationCode) verificationScreen.submitCode() _ = mainTabs.waitForExistence(timeout: loginTimeout) || tabBar.waitForExistence(timeout: 5) break } RunLoop.current.run(until: Date().addingTimeInterval(0.5)) } XCTAssertTrue(mainTabs.exists || tabBar.exists, "Expected main app root to appear after login (with verification handling)") main.goToResidences() } @discardableResult private func createResidence(name: String) -> String { loginAndOpenResidences() let list = ResidenceListScreen(app: app) list.waitForLoad(timeout: defaultTimeout) list.openCreateResidence() let form = ResidenceFormScreen(app: app) form.waitForLoad(timeout: defaultTimeout) form.enterName(name) form.save() return name } func testR301_authenticatedPreconditionCanReachMainApp() throws { loginAndOpenResidences() RebuildSessionAssertions.assertOnMainApp(app, timeout: defaultTimeout) } func testR302_residencesTabIsPresentAndNavigable() throws { loginAndOpenResidences() let residencesTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch XCTAssertTrue(residencesTab.exists, "Residences tab should exist") } func testR303_residencesListLoadsAfterTabSelection() throws { loginAndOpenResidences() let list = ResidenceListScreen(app: app) list.waitForLoad(timeout: defaultTimeout) XCTAssertTrue(list.addButton.exists, "Add residence button should be visible") } func testR304_openAddResidenceFormFromResidencesList() throws { loginAndOpenResidences() let list = ResidenceListScreen(app: app) list.waitForLoad(timeout: defaultTimeout) list.openCreateResidence() let form = ResidenceFormScreen(app: app) form.waitForLoad(timeout: defaultTimeout) XCTAssertTrue(form.saveButton.exists, "Residence save button should exist") } func testR305_cancelAddResidenceReturnsToResidenceList() throws { loginAndOpenResidences() let list = ResidenceListScreen(app: app) list.openCreateResidence() let form = ResidenceFormScreen(app: app) form.waitForLoad(timeout: defaultTimeout) form.cancel() list.waitForLoad(timeout: defaultTimeout) } func testR306_createResidenceMinimalDataSubmitsSuccessfully() throws { let name = "UITest Home \(Int(Date().timeIntervalSince1970))" _ = createResidence(name: name) let created = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] %@", name)).firstMatch XCTAssertTrue(created.waitForExistence(timeout: loginTimeout), "Created residence should appear in list") } func testR307_newResidenceAppearsInResidenceList() throws { let name = "UITest Verify \(Int(Date().timeIntervalSince1970))" _ = createResidence(name: name) let created = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] %@", name)).firstMatch XCTAssertTrue(created.waitForExistence(timeout: loginTimeout), "New residence should be visible in residences list") } func testR308_openResidenceDetailsFromResidenceList() throws { let name = "UITest Detail \(Int(Date().timeIntervalSince1970))" _ = createResidence(name: name) let row = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] %@", name)).firstMatch row.waitForExistenceOrFail(timeout: loginTimeout).forceTap() let edit = app.buttons[AccessibilityIdentifiers.Residence.editButton] let delete = app.buttons[AccessibilityIdentifiers.Residence.deleteButton] let loaded = edit.waitForExistence(timeout: defaultTimeout) || delete.waitForExistence(timeout: defaultTimeout) XCTAssertTrue(loaded, "Residence details should expose edit or delete actions") } func testR309_navigationAcrossPrimaryTabsAndBackToResidences() throws { loginAndOpenResidences() let tabBar = app.tabBars.firstMatch tabBar.waitForExistenceOrFail(timeout: defaultTimeout) let tasksTab = tabBar.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Tasks'")).firstMatch XCTAssertTrue(tasksTab.exists, "Tasks tab should exist") tasksTab.forceTap() let contractorsTab = tabBar.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Contractors'")).firstMatch XCTAssertTrue(contractorsTab.exists, "Contractors tab should exist") contractorsTab.forceTap() let residencesTab = tabBar.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch residencesTab.forceTap() let list = ResidenceListScreen(app: app) list.waitForLoad(timeout: defaultTimeout) } }