import XCTest /// Comprehensive residence testing suite covering all scenarios, edge cases, and variations /// This test suite is designed to be bulletproof and catch regressions early /// /// Test Order (least to most complex): /// 1. Error/incomplete data tests /// 2. Creation tests /// 3. Edit/update tests /// 4. Delete/remove tests (none currently) /// 5. Navigation/view tests /// 6. Performance tests final class Suite4_ComprehensiveResidenceTests: XCTestCase { var app: XCUIApplication! // Test data tracking var createdResidenceNames: [String] = [] override func setUpWithError() throws { continueAfterFailure = false app = XCUIApplication() app.launch() // Ensure user is logged in UITestHelpers.ensureLoggedIn(app: app) // Navigate to Residences tab navigateToResidencesTab() } override func tearDownWithError() throws { createdResidenceNames.removeAll() app = nil } // MARK: - Helper Methods private func navigateToResidencesTab() { let residencesTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch if residencesTab.waitForExistence(timeout: 5) { if !residencesTab.isSelected { residencesTab.tap() sleep(3) } } } private func openResidenceForm() -> Bool { let addButton = findAddResidenceButton() guard addButton.exists && addButton.isEnabled else { return false } addButton.tap() sleep(3) // Verify form opened let nameField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Name'")).firstMatch return nameField.waitForExistence(timeout: 5) } private func findAddResidenceButton() -> XCUIElement { sleep(2) let addButtonById = app.buttons[AccessibilityIdentifiers.Residence.addButton] if addButtonById.exists && addButtonById.isEnabled { return addButtonById } let navBarButtons = app.navigationBars.buttons for i in 0.. Bool { guard openResidenceForm() else { return false } // Fill name let nameField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Name'")).firstMatch nameField.tap() nameField.typeText(name) // Select property type selectPropertyType(type: propertyType) // Scroll to address section if scrollBeforeAddress { app.swipeUp() sleep(1) } // Fill address fields fillTextField(placeholder: "Street", text: street) fillTextField(placeholder: "City", text: city) fillTextField(placeholder: "State", text: state) fillTextField(placeholder: "Postal", text: postal) // Save let saveButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Save'")).firstMatch guard saveButton.exists else { return false } saveButton.tap() sleep(4) // Wait for API call // Track created residence createdResidenceNames.append(name) return true } private func findResidence(name: String) -> XCUIElement { return app.staticTexts.containing(NSPredicate(format: "label CONTAINS '\(name)'")).firstMatch } // MARK: - 1. Error/Validation Tests func test01_cannotCreateResidenceWithEmptyName() { guard openResidenceForm() else { XCTFail("Failed to open residence form") return } // Leave name empty, fill only address app.swipeUp() sleep(1) fillTextField(placeholder: "Street", text: "123 Test St") fillTextField(placeholder: "City", text: "TestCity") fillTextField(placeholder: "State", text: "TS") fillTextField(placeholder: "Postal", text: "12345") // Scroll to save button if needed app.swipeUp() sleep(1) // Save button should be disabled when name is empty let saveButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Save'")).firstMatch XCTAssertTrue(saveButton.exists, "Save button should exist") XCTAssertFalse(saveButton.isEnabled, "Save button should be disabled when name is empty") } func test02_cancelResidenceCreation() { guard openResidenceForm() else { XCTFail("Failed to open residence form") return } // Fill some data let nameField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Name'")).firstMatch nameField.tap() nameField.typeText("This will be canceled") // Tap cancel let cancelButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Cancel'")).firstMatch XCTAssertTrue(cancelButton.exists, "Cancel button should exist") cancelButton.tap() sleep(2) // Should be back on residences list let residencesTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch XCTAssertTrue(residencesTab.exists, "Should be back on residences list") // Residence should not exist let residence = findResidence(name: "This will be canceled") XCTAssertFalse(residence.exists, "Canceled residence should not exist") } // MARK: - 2. Creation Tests func test03_createResidenceWithMinimalData() { let timestamp = Int(Date().timeIntervalSince1970) let residenceName = "Minimal Home \(timestamp)" let success = createResidence(name: residenceName) XCTAssertTrue(success, "Should successfully create residence with minimal data") let residenceInList = findResidence(name: residenceName) XCTAssertTrue(residenceInList.waitForExistence(timeout: 10), "Residence should appear in list") } func test04_createResidenceWithAllPropertyTypes() { let timestamp = Int(Date().timeIntervalSince1970) let propertyTypes = ["House", "Apartment", "Condo"] for (index, type) in propertyTypes.enumerated() { let residenceName = "\(type) Test \(timestamp)_\(index)" let success = createResidence(name: residenceName, propertyType: type) XCTAssertTrue(success, "Should create \(type) residence") navigateToResidencesTab() sleep(2) } // Verify all residences exist for (index, type) in propertyTypes.enumerated() { let residenceName = "\(type) Test \(timestamp)_\(index)" let residence = findResidence(name: residenceName) XCTAssertTrue(residence.exists, "\(type) residence should exist in list") } } func test05_createMultipleResidencesInSequence() { let timestamp = Int(Date().timeIntervalSince1970) for i in 1...3 { let residenceName = "Sequential Home \(i) - \(timestamp)" let success = createResidence(name: residenceName) XCTAssertTrue(success, "Should create residence \(i)") navigateToResidencesTab() sleep(2) } // Verify all residences exist for i in 1...3 { let residenceName = "Sequential Home \(i) - \(timestamp)" let residence = findResidence(name: residenceName) XCTAssertTrue(residence.exists, "Residence \(i) should exist in list") } } func test06_createResidenceWithVeryLongName() { let timestamp = Int(Date().timeIntervalSince1970) let longName = "This is an extremely long residence name that goes on and on and on to test how the system handles very long text input in the name field \(timestamp)" let success = createResidence(name: longName) XCTAssertTrue(success, "Should handle very long names") // Verify it appears (may be truncated in display) let residence = app.staticTexts.containing(NSPredicate(format: "label CONTAINS 'extremely long residence'")).firstMatch XCTAssertTrue(residence.waitForExistence(timeout: 10), "Long name residence should exist") } func test07_createResidenceWithSpecialCharacters() { let timestamp = Int(Date().timeIntervalSince1970) let specialName = "Special !@#$%^&*() Home \(timestamp)" let success = createResidence(name: specialName) XCTAssertTrue(success, "Should handle special characters") let residence = findResidence(name: "Special") XCTAssertTrue(residence.waitForExistence(timeout: 10), "Residence with special chars should exist") } func test08_createResidenceWithEmojis() { let timestamp = Int(Date().timeIntervalSince1970) let emojiName = "Beach House \(timestamp)" let success = createResidence(name: emojiName) XCTAssertTrue(success, "Should handle emojis") let residence = findResidence(name: "Beach House") XCTAssertTrue(residence.waitForExistence(timeout: 10), "Residence with emojis should exist") } func test09_createResidenceWithInternationalCharacters() { let timestamp = Int(Date().timeIntervalSince1970) let internationalName = "Chateau Montreal \(timestamp)" let success = createResidence(name: internationalName) XCTAssertTrue(success, "Should handle international characters") let residence = findResidence(name: "Chateau") XCTAssertTrue(residence.waitForExistence(timeout: 10), "Residence with international chars should exist") } func test10_createResidenceWithVeryLongAddress() { let timestamp = Int(Date().timeIntervalSince1970) let residenceName = "Long Address Home \(timestamp)" let success = createResidence( name: residenceName, street: "123456789 Very Long Street Name That Goes On And On Boulevard Apartment Complex Unit 42B", city: "VeryLongCityNameThatTestsTheLimit", state: "CA", postal: "12345-6789" ) XCTAssertTrue(success, "Should handle very long addresses") let residence = findResidence(name: residenceName) XCTAssertTrue(residence.waitForExistence(timeout: 10), "Residence with long address should exist") } // MARK: - 3. Edit/Update Tests func test11_editResidenceName() { let timestamp = Int(Date().timeIntervalSince1970) let originalName = "Original Name \(timestamp)" let newName = "Edited Name \(timestamp)" // Create residence guard createResidence(name: originalName) else { XCTFail("Failed to create residence") return } navigateToResidencesTab() sleep(2) // Find and tap residence let residence = findResidence(name: originalName) XCTAssertTrue(residence.waitForExistence(timeout: 5), "Residence should exist") residence.tap() sleep(2) // Tap edit button let editButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Edit'")).firstMatch if editButton.exists { editButton.tap() sleep(2) // Edit name let nameField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Name'")).firstMatch if nameField.exists { let element = app/*@START_MENU_TOKEN@*/.textFields["ResidenceForm.NameField"]/*[[".otherElements",".textFields[\"Original Name 1764809003\"]",".textFields[\"Property Name\"]",".textFields[\"ResidenceForm.NameField\"]"],[[[-1,3],[-1,2],[-1,1],[-1,0,1]],[[-1,3],[-1,2],[-1,1]]],[0]]@END_MENU_TOKEN@*/.firstMatch element.tap() element.tap() app/*@START_MENU_TOKEN@*/.menuItems["Select All"]/*[[".menuItems.containing(.staticText, identifier: \"Select All\")",".collectionViews.menuItems[\"Select All\"]",".menuItems[\"Select All\"]"],[[[-1,2],[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.firstMatch.tap() nameField.typeText(newName) // Save let saveButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Save'")).firstMatch if saveButton.exists { saveButton.tap() sleep(3) // Track new name createdResidenceNames.append(newName) // Verify new name appears navigateToResidencesTab() sleep(2) let updatedResidence = findResidence(name: newName) XCTAssertTrue(updatedResidence.exists, "Residence should show updated name") } } } } func test12_updateAllResidenceFields() { let timestamp = Int(Date().timeIntervalSince1970) let originalName = "Update All Fields \(timestamp)" let newName = "All Fields Updated \(timestamp)" let newStreet = "999 Updated Avenue" let newCity = "NewCity" let newState = "NC" let newPostal = "99999" // Create residence with initial values guard createResidence(name: originalName, street: "123 Old St", city: "OldCity", state: "OC", postal: "11111") else { XCTFail("Failed to create residence") return } navigateToResidencesTab() sleep(2) // Find and tap residence let residence = findResidence(name: originalName) XCTAssertTrue(residence.waitForExistence(timeout: 5), "Residence should exist") residence.tap() sleep(2) // Tap edit button let editButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Edit'")).firstMatch XCTAssertTrue(editButton.exists, "Edit button should exist") editButton.tap() sleep(2) // Update name let nameField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Name'")).firstMatch XCTAssertTrue(nameField.exists, "Name field should exist") nameField.tap() nameField.doubleTap() sleep(1) if app.buttons["Select All"].exists { app.buttons["Select All"].tap() sleep(1) } nameField.typeText(newName) // Update property type (if available) let propertyTypePicker = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Property Type'")).firstMatch if propertyTypePicker.exists { propertyTypePicker.tap() sleep(1) // Select Condo let condoOption = app.buttons["Condo"] if condoOption.exists { condoOption.tap() sleep(1) } else { // Try cells navigation let cells = app.cells for i in 0..