import XCTest /// Comprehensive contractor testing suite covering all scenarios, edge cases, and variations /// This test suite is designed to be bulletproof and catch regressions early final class Suite7_ContractorTests: XCTestCase { var app: XCUIApplication! // Test data tracking var createdContractorNames: [String] = [] override func setUpWithError() throws { continueAfterFailure = false app = XCUIApplication() app.launch() // Ensure user is logged in UITestHelpers.ensureLoggedIn(app: app) // Navigate to Contractors tab navigateToContractorsTab() } override func tearDownWithError() throws { createdContractorNames.removeAll() app = nil } // MARK: - Helper Methods private func navigateToContractorsTab() { let contractorsTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Contractors'")).firstMatch if contractorsTab.waitForExistence(timeout: 5) { if !contractorsTab.isSelected { contractorsTab.tap() sleep(3) } } } private func openContractorForm() -> Bool { let addButton = findAddContractorButton() 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 findAddContractorButton() -> XCUIElement { sleep(2) // Look for add button by various methods let navBarButtons = app.navigationBars.buttons for i in 0.. Bool { guard openContractorForm() else { return false } // Fill name let nameField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Name'")).firstMatch nameField.tap() nameField.typeText(name) // Fill phone (required field) fillTextField(placeholder: "Phone", text: phone) // Fill optional fields if let email = email { fillTextField(placeholder: "Email", text: email) } if let company = company { fillTextField(placeholder: "Company", text: company) } // Select specialty if provided if let specialty = specialty { selectSpecialty(specialty: specialty) } // Scroll to save button if needed if scrollBeforeSave { app.swipeUp() sleep(1) } // Add button (for creating new contractors) let addButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Add'")).firstMatch guard addButton.exists else { return false } addButton.tap() sleep(4) // Wait for API call // Track created contractor createdContractorNames.append(name) return true } private func findContractor(name: String, scrollIfNeeded: Bool = true) -> XCUIElement { let element = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] %@", name)).firstMatch // If element is visible, return it immediately if element.exists && element.isHittable { return element } // If scrolling is not needed, return the element as-is guard scrollIfNeeded else { return element } // Get the scroll view let scrollView = app.scrollViews.firstMatch guard scrollView.exists else { return element } // First, scroll to the top of the list scrollView.swipeDown(velocity: .fast) usleep(30_000) // 0.03 second delay // Now scroll down from top, checking after each swipe var lastVisibleRow = "" for _ in 0..