Files
honeyDueKMP/iosApp/CaseraUITests/Suite8_DocumentWarrantyTests.swift
Trey t b0838d85df Add residence picker to contractor create/edit screens
Kotlin/KMM:
- Update Contractor model with optional residenceId and specialties array
- Rename averageRating to rating, update address field names
- Add ContractorMinimal model for task references
- Add residence picker and multi-select specialty chips to AddContractorDialog
- Fix ContractorsScreen and ContractorDetailScreen field references

iOS:
- Rewrite ContractorFormSheet with residence and specialty pickers
- Update ContractorDetailView with FlowLayout for specialties
- Add FlowLayout component for wrapping badge layouts
- Fix ContractorCard and CompleteTaskView field references
- Update ContractorFormState with residence/specialty selection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 18:42:18 -06:00

946 lines
35 KiB
Swift

import XCTest
/// Comprehensive documents and warranties testing suite covering all scenarios, edge cases, and variations
/// Tests both document types (permits, receipts, etc.) and warranties with filtering, searching, and CRUD operations
final class Suite8_DocumentWarrantyTests: XCTestCase {
var app: XCUIApplication!
// Test data tracking
var createdDocumentTitles: [String] = []
var currentResidenceId: Int32?
override func setUpWithError() throws {
continueAfterFailure = false
app = XCUIApplication()
app.launch()
// Ensure user is logged in
UITestHelpers.ensureLoggedIn(app: app)
// Navigate to a residence first (documents are residence-specific)
navigateToFirstResidence()
}
override func tearDownWithError() throws {
createdDocumentTitles.removeAll()
currentResidenceId = nil
app = nil
}
// MARK: - Helper Methods
private func navigateToFirstResidence() {
// Tap Residences tab
let residencesTab = app.tabBars.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Residences'")).firstMatch
if residencesTab.waitForExistence(timeout: 5) {
residencesTab.tap()
sleep(3)
}
// Tap first residence card
let firstResidence = app.collectionViews.cells.firstMatch
if firstResidence.waitForExistence(timeout: 5) {
firstResidence.tap()
sleep(2)
}
}
private func navigateToDocumentsTab() {
// Look for Documents tab or navigation link
let documentsButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Documents' OR label CONTAINS[c] 'Warranties'")).firstMatch
if documentsButton.waitForExistence(timeout: 5) {
documentsButton.tap()
sleep(3)
}
}
private func openDocumentForm() -> Bool {
let addButton = findAddButton()
guard addButton.exists && addButton.isEnabled else { return false }
addButton.tap()
sleep(3)
// Verify form opened
let titleField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'Title'")).firstMatch
return titleField.waitForExistence(timeout: 5)
}
private func findAddButton() -> XCUIElement {
sleep(2)
// Look for add button by various methods
let navBarButtons = app.navigationBars.buttons
for i in 0..<navBarButtons.count {
let button = navBarButtons.element(boundBy: i)
if button.label == "plus" || button.label.contains("Add") {
if button.isEnabled {
return button
}
}
}
// Fallback: look for any button with plus icon
return app.buttons.containing(NSPredicate(format: "label CONTAINS 'plus'")).firstMatch
}
private func fillTextField(placeholder: String, text: String) {
let field = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] '\(placeholder)'")).firstMatch
if field.exists {
field.tap()
field.typeText(text)
}
}
private func fillTextEditor(text: String) {
let textEditor = app.textViews.firstMatch
if textEditor.exists {
textEditor.tap()
textEditor.typeText(text)
}
}
private func selectProperty() {
// Open the picker
app.buttons["Select Property, Select Property"].tap()
// Try cells first (common for Picker list)
let secondCell = app.cells.element(boundBy: 1)
if secondCell.waitForExistence(timeout: 5) {
secondCell.tap()
} else {
// Fallback: second static text after the title
let allTexts = app.staticTexts.allElementsBoundByIndex
// Expect something like: [ "Select Property" (title), "Select Property", "Test Home for Comprehensive Tasks", ... ]
// So the second item row label is usually at index 2
let secondItemText = allTexts[2]
secondItemText.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
}
}
private func selectDocumentType(type: String) {
let typePicker = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Type'")).firstMatch
if typePicker.exists {
typePicker.tap()
sleep(1)
let typeButton = app.buttons[type]
if typeButton.exists {
typeButton.tap()
sleep(1)
} else {
// Try cells if it's a navigation style picker
let cells = app.cells
for i in 0..<cells.count {
let cell = cells.element(boundBy: i)
if cell.staticTexts[type].exists {
cell.tap()
sleep(1)
break
}
}
}
}
}
private func selectCategory(category: String) {
let categoryPicker = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Category'")).firstMatch
if categoryPicker.exists {
categoryPicker.tap()
sleep(1)
let categoryButton = app.buttons[category]
if categoryButton.exists {
categoryButton.tap()
sleep(1)
} else {
let cells = app.cells
for i in 0..<cells.count {
let cell = cells.element(boundBy: i)
if cell.staticTexts[category].exists {
cell.tap()
sleep(1)
break
}
}
}
}
}
private func selectDate(dateType: String, daysFromNow: Int) {
let datePicker = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] '\(dateType)'")).firstMatch
if datePicker.exists {
datePicker.tap()
sleep(1)
// Look for date picker and set date
let datePickerWheel = app.datePickers.firstMatch
if datePickerWheel.exists {
let calendar = Calendar.current
let targetDate = calendar.date(byAdding: .day, value: daysFromNow, to: Date())!
let formatter = DateFormatter()
formatter.dateFormat = "MMM d, yyyy"
let dateString = formatter.string(from: targetDate)
// Try to type the date or interact with picker
sleep(1)
}
// Dismiss picker
app.buttons["Done"].tap()
sleep(1)
}
}
private func submitForm() -> Bool {
let submitButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Save' OR label CONTAINS[c] 'Add' OR label CONTAINS[c] 'Create'")).firstMatch
guard submitButton.exists && submitButton.isEnabled else { return false }
submitButton.tap()
sleep(3)
return true
}
private func cancelForm() {
let cancelButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Cancel'")).firstMatch
if cancelButton.exists {
cancelButton.tap()
sleep(2)
}
}
private func switchToWarrantiesTab() {
app/*@START_MENU_TOKEN@*/.buttons["checkmark.shield"]/*[[".segmentedControls",".buttons[\"Warranties\"]",".buttons[\"checkmark.shield\"]"],[[[-1,2],[-1,1],[-1,0,1]],[[-1,2],[-1,1]]],[0]]@END_MENU_TOKEN@*/.firstMatch.tap()
}
private func switchToDocumentsTab() {
app/*@START_MENU_TOKEN@*/.buttons["doc.text"]/*[[".segmentedControls",".buttons[\"Documents\"]",".buttons[\"doc.text\"]"],[[[-1,2],[-1,0,1]],[[-1,2],[-1,1]]],[0]]@END_MENU_TOKEN@*/.firstMatch.tap()
}
private func searchFor(text: String) {
let searchField = app.searchFields.firstMatch
if searchField.exists {
searchField.tap()
searchField.typeText(text)
sleep(2)
}
}
private func clearSearch() {
let searchField = app.searchFields.firstMatch
if searchField.exists {
let clearButton = searchField.buttons["Clear text"]
if clearButton.exists {
clearButton.tap()
sleep(1)
}
}
}
private func applyFilter(filterName: String) {
// Open filter menu
let filterButton = app.buttons.containing(NSPredicate(format: "label CONTAINS 'line.3.horizontal.decrease'")).firstMatch
if filterButton.exists {
filterButton.tap()
sleep(1)
// Select filter option
let filterOption = app.buttons[filterName]
if filterOption.exists {
filterOption.tap()
sleep(2)
}
}
}
private func toggleActiveFilter() {
let activeFilterButton = app.buttons.containing(NSPredicate(format: "label CONTAINS 'checkmark.circle'")).firstMatch
if activeFilterButton.exists {
activeFilterButton.tap()
sleep(2)
}
}
// MARK: - Test Cases
// MARK: Navigation Tests
func test01_NavigateToDocumentsScreen() {
navigateToDocumentsTab()
// Verify we're on documents screen
let navigationTitle = app.navigationBars["Documents & Warranties"]
XCTAssertTrue(navigationTitle.waitForExistence(timeout: 5), "Should navigate to Documents & Warranties screen")
// Verify tabs are visible
let warrantiesTab = app.buttons["Warranties"]
let documentsTab = app.buttons["Documents"]
XCTAssertTrue(warrantiesTab.exists || documentsTab.exists, "Should see tab switcher")
}
func test02_SwitchBetweenWarrantiesAndDocuments() {
navigateToDocumentsTab()
// Start on warranties tab
switchToWarrantiesTab()
sleep(1)
// Switch to documents tab
switchToDocumentsTab()
sleep(1)
// Switch back to warranties
switchToWarrantiesTab()
sleep(1)
// Should not crash and tabs should still exist
let warrantiesTab = app.buttons["Warranties"]
XCTAssertTrue(warrantiesTab.exists, "Tabs should remain functional after switching")
}
// MARK: Document Creation Tests
func test03_CreateDocumentWithAllFields() {
navigateToDocumentsTab()
switchToDocumentsTab()
XCTAssertTrue(openDocumentForm(), "Should open document form")
let testTitle = "Test Permit \(UUID().uuidString.prefix(8))"
createdDocumentTitles.append(testTitle)
// Fill all fields
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: testTitle)
selectDocumentType(type: "Insurance")
fillTextEditor(text: "Test permit description with detailed information")
fillTextField(placeholder: "Tags", text: "construction,permit")
fillTextField(placeholder: "Item Name", text: "Kitchen Renovation")
fillTextField(placeholder: "Location", text: "Main Kitchen")
XCTAssertTrue(submitForm(), "Should submit form successfully")
// Verify document appears in list
sleep(2)
let documentCard = app.staticTexts[testTitle]
XCTAssertTrue(documentCard.exists, "Created document should appear in list")
}
func test04_CreateDocumentWithMinimalFields() {
navigateToDocumentsTab()
switchToDocumentsTab()
XCTAssertTrue(openDocumentForm(), "Should open document form")
let testTitle = "Min Doc \(UUID().uuidString.prefix(8))"
createdDocumentTitles.append(testTitle)
// Fill only required fields
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: testTitle)
selectDocumentType(type: "Insurance")
XCTAssertTrue(submitForm(), "Should submit form with minimal fields")
// Verify document appears
sleep(2)
let documentCard = app.staticTexts[testTitle]
XCTAssertTrue(documentCard.exists, "Document with minimal fields should appear")
}
func test05_CreateDocumentWithEmptyTitle_ShouldFail() {
navigateToDocumentsTab()
switchToDocumentsTab()
XCTAssertTrue(openDocumentForm(), "Should open document form")
// Try to submit without title
selectProperty() // REQUIRED - Select property first
selectDocumentType(type: "Insurance")
let submitButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Save' OR label CONTAINS[c] 'Add'")).firstMatch
// Submit button should be disabled or show error
if submitButton.exists && submitButton.isEnabled {
submitButton.tap()
sleep(2)
// Should show error message
let errorMessage = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'required' OR label CONTAINS[c] 'title'")).firstMatch
XCTAssertTrue(errorMessage.exists, "Should show validation error for missing title")
}
cancelForm()
}
// MARK: Warranty Creation Tests
func test06_CreateWarrantyWithAllFields() {
navigateToDocumentsTab()
switchToWarrantiesTab()
XCTAssertTrue(openDocumentForm(), "Should open warranty form")
let testTitle = "Test Warranty \(UUID().uuidString.prefix(8))"
createdDocumentTitles.append(testTitle)
// Fill all warranty fields (including required fields)
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: testTitle)
selectCategory(category: "Appliances")
fillTextField(placeholder: "Item Name", text: "Dishwasher") // REQUIRED
fillTextField(placeholder: "Provider", text: "Bosch") // REQUIRED
fillTextField(placeholder: "Model", text: "SHPM65Z55N")
fillTextField(placeholder: "Serial", text: "SN123456789")
fillTextField(placeholder: "Provider Contact", text: "1-800-BOSCH-00")
fillTextEditor(text: "Full warranty coverage for 2 years")
// Select dates
selectDate(dateType: "Start Date", daysFromNow: -30)
selectDate(dateType: "End Date", daysFromNow: 700) // ~2 years
XCTAssertTrue(submitForm(), "Should submit warranty successfully")
// Verify warranty appears
sleep(2)
let warrantyCard = app.staticTexts[testTitle]
XCTAssertTrue(warrantyCard.exists, "Created warranty should appear in list")
}
func test07_CreateWarrantyWithFutureDates() {
navigateToDocumentsTab()
switchToWarrantiesTab()
XCTAssertTrue(openDocumentForm(), "Should open warranty form")
let testTitle = "Future Warranty \(UUID().uuidString.prefix(8))"
createdDocumentTitles.append(testTitle)
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: testTitle)
selectCategory(category: "HVAC")
fillTextField(placeholder: "Item Name", text: "Air Conditioner") // REQUIRED
fillTextField(placeholder: "Provider", text: "Carrier HVAC") // REQUIRED
// Set start date in future
selectDate(dateType: "Start Date", daysFromNow: 30)
selectDate(dateType: "End Date", daysFromNow: 400)
XCTAssertTrue(submitForm(), "Should create warranty with future dates")
sleep(2)
let warrantyCard = app.staticTexts[testTitle]
XCTAssertTrue(warrantyCard.exists, "Warranty with future dates should be created")
}
func test08_CreateExpiredWarranty() {
navigateToDocumentsTab()
switchToWarrantiesTab()
XCTAssertTrue(openDocumentForm(), "Should open warranty form")
let testTitle = "Expired Warranty \(UUID().uuidString.prefix(8))"
createdDocumentTitles.append(testTitle)
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: testTitle)
selectCategory(category: "Plumbing")
fillTextField(placeholder: "Item Name", text: "Water Heater") // REQUIRED
fillTextField(placeholder: "Provider", text: "AO Smith") // REQUIRED
// Set dates in the past
selectDate(dateType: "Start Date", daysFromNow: -400)
selectDate(dateType: "End Date", daysFromNow: -30)
XCTAssertTrue(submitForm(), "Should create expired warranty")
sleep(2)
// Expired warranty might not show with active filter on
// Toggle active filter off to see it
toggleActiveFilter()
sleep(1)
let warrantyCard = app.staticTexts[testTitle]
XCTAssertTrue(warrantyCard.exists, "Expired warranty should be created and visible when filter is off")
}
// MARK: Search and Filter Tests
func test09_SearchDocumentsByTitle() {
navigateToDocumentsTab()
switchToDocumentsTab()
// Create a test document first
XCTAssertTrue(openDocumentForm(), "Should open form")
let searchableTitle = "Searchable Doc \(UUID().uuidString.prefix(8))"
createdDocumentTitles.append(searchableTitle)
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: searchableTitle)
selectDocumentType(type: "Insurance")
XCTAssertTrue(submitForm(), "Should create document")
sleep(2)
// Search for it
searchFor(text: String(searchableTitle.prefix(15)))
// Should find the document
let foundDocument = app.staticTexts[searchableTitle]
XCTAssertTrue(foundDocument.exists, "Should find document by search")
clearSearch()
}
func test10_FilterWarrantiesByCategory() {
navigateToDocumentsTab()
switchToWarrantiesTab()
// Apply category filter
applyFilter(filterName: "Appliances")
sleep(2)
// Should show filter chip or indication
let filterChip = app.staticTexts["Appliances"]
XCTAssertTrue(filterChip.exists || app.buttons["Appliances"].exists, "Should show active category filter")
// Clear filter
applyFilter(filterName: "All Categories")
}
func test11_FilterDocumentsByType() {
navigateToDocumentsTab()
switchToDocumentsTab()
// Apply type filter
applyFilter(filterName: "Permit")
sleep(2)
// Should show filter indication
let filterChip = app.staticTexts["Permit"]
XCTAssertTrue(filterChip.exists || app.buttons["Permit"].exists, "Should show active type filter")
// Clear filter
applyFilter(filterName: "All Types")
}
func test12_ToggleActiveWarrantiesFilter() {
navigateToDocumentsTab()
switchToWarrantiesTab()
// Toggle active filter off
toggleActiveFilter()
sleep(1)
// Toggle it back on
toggleActiveFilter()
sleep(1)
// Should not crash
let warrantiesTab = app.buttons["Warranties"]
XCTAssertTrue(warrantiesTab.exists, "Active filter toggle should work without crashing")
}
// MARK: Document Detail Tests
func test13_ViewDocumentDetail() {
navigateToDocumentsTab()
switchToDocumentsTab()
// Create a document
XCTAssertTrue(openDocumentForm(), "Should open form")
let testTitle = "Detail Test Doc \(UUID().uuidString.prefix(8))"
createdDocumentTitles.append(testTitle)
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: testTitle)
selectDocumentType(type: "Insurance")
fillTextEditor(text: "This is a test receipt with details")
XCTAssertTrue(submitForm(), "Should create document")
sleep(2)
// Tap on the document card
let documentCard = app.staticTexts[testTitle]
XCTAssertTrue(documentCard.exists, "Document should exist in list")
documentCard.tap()
sleep(2)
// Should show detail screen
let detailTitle = app.staticTexts[testTitle]
XCTAssertTrue(detailTitle.exists, "Should show document detail screen")
// Go back
let backButton = app.navigationBars.buttons.firstMatch
backButton.tap()
sleep(1)
}
func test14_ViewWarrantyDetailWithDates() {
navigateToDocumentsTab()
switchToWarrantiesTab()
// Create a warranty
XCTAssertTrue(openDocumentForm(), "Should open form")
let testTitle = "Warranty Detail Test \(UUID().uuidString.prefix(8))"
createdDocumentTitles.append(testTitle)
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: testTitle)
selectCategory(category: "Appliances")
fillTextField(placeholder: "Item Name", text: "Test Appliance") // REQUIRED
fillTextField(placeholder: "Provider", text: "Test Company") // REQUIRED
selectDate(dateType: "Start Date", daysFromNow: -30)
selectDate(dateType: "End Date", daysFromNow: 335)
XCTAssertTrue(submitForm(), "Should create warranty")
sleep(2)
// Tap on warranty
let warrantyCard = app.staticTexts[testTitle]
XCTAssertTrue(warrantyCard.exists, "Warranty should exist")
warrantyCard.tap()
sleep(2)
// Should show warranty details with dates
let detailScreen = app.staticTexts[testTitle]
XCTAssertTrue(detailScreen.exists, "Should show warranty detail")
// Look for date information
let dateLabels = app.staticTexts.matching(NSPredicate(format: "label CONTAINS[c] '20' OR label CONTAINS[c] 'Start' OR label CONTAINS[c] 'End'"))
XCTAssertTrue(dateLabels.count > 0, "Should display date information")
// Go back
app.navigationBars.buttons.firstMatch.tap()
sleep(1)
}
// MARK: Edit Tests
func test15_EditDocumentTitle() {
navigateToDocumentsTab()
switchToDocumentsTab()
// Create document
XCTAssertTrue(openDocumentForm(), "Should open form")
let originalTitle = "Edit Test \(UUID().uuidString.prefix(8))"
createdDocumentTitles.append(originalTitle)
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: originalTitle)
selectDocumentType(type: "Insurance")
XCTAssertTrue(submitForm(), "Should create document")
sleep(2)
// Open detail
let documentCard = app.staticTexts[originalTitle]
XCTAssertTrue(documentCard.exists, "Document should exist")
documentCard.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)
// Change title
let titleField = app.textFields.containing(NSPredicate(format: "value == '\(originalTitle)'")).firstMatch
if titleField.exists {
titleField.tap()
titleField.clearText()
let newTitle = "Edited \(originalTitle)"
titleField.typeText(newTitle)
createdDocumentTitles.append(newTitle)
XCTAssertTrue(submitForm(), "Should save edited document")
sleep(2)
// Verify new title appears
let updatedTitle = app.staticTexts[newTitle]
XCTAssertTrue(updatedTitle.exists, "Updated title should appear")
}
}
// Go back to list
app.navigationBars.buttons.element(boundBy: 0).tap()
sleep(1)
}
func test16_EditWarrantyDates() {
navigateToDocumentsTab()
switchToWarrantiesTab()
// Create warranty
XCTAssertTrue(openDocumentForm(), "Should open form")
let testTitle = "Edit Dates Warranty \(UUID().uuidString.prefix(8))"
createdDocumentTitles.append(testTitle)
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: testTitle)
selectCategory(category: "Electronics")
fillTextField(placeholder: "Item Name", text: "TV") // REQUIRED
fillTextField(placeholder: "Provider", text: "Samsung") // REQUIRED
selectDate(dateType: "Start Date", daysFromNow: -60)
selectDate(dateType: "End Date", daysFromNow: 305)
XCTAssertTrue(submitForm(), "Should create warranty")
sleep(2)
// Open and edit
let warrantyCard = app.staticTexts[testTitle]
XCTAssertTrue(warrantyCard.exists, "Warranty should exist")
warrantyCard.tap()
sleep(2)
let editButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Edit'")).firstMatch
if editButton.exists {
editButton.tap()
sleep(2)
// Change end date to extend warranty
selectDate(dateType: "End Date", daysFromNow: 730) // 2 years
XCTAssertTrue(submitForm(), "Should save edited warranty dates")
sleep(2)
}
app.navigationBars.buttons.element(boundBy: 0).tap()
sleep(1)
}
// MARK: Delete Tests
func test17_DeleteDocument() {
navigateToDocumentsTab()
switchToDocumentsTab()
// Create document to delete
XCTAssertTrue(openDocumentForm(), "Should open form")
let deleteTitle = "To Delete \(UUID().uuidString.prefix(8))"
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: deleteTitle)
selectDocumentType(type: "Insurance")
XCTAssertTrue(submitForm(), "Should create document")
sleep(2)
// Open detail
let documentCard = app.staticTexts[deleteTitle]
XCTAssertTrue(documentCard.exists, "Document should exist")
documentCard.tap()
sleep(2)
// Find and tap delete button
let deleteButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Delete' OR label CONTAINS[c] 'trash'")).firstMatch
if deleteButton.exists {
deleteButton.tap()
sleep(1)
// Confirm deletion
let confirmButton = app.alerts.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Delete' OR label CONTAINS[c] 'Confirm'")).firstMatch
if confirmButton.exists {
confirmButton.tap()
sleep(2)
}
// Should navigate back to list
sleep(2)
// Verify document no longer exists
let deletedCard = app.staticTexts[deleteTitle]
XCTAssertFalse(deletedCard.exists, "Deleted document should not appear in list")
}
}
func test18_DeleteWarranty() {
navigateToDocumentsTab()
switchToWarrantiesTab()
// Create warranty to delete
XCTAssertTrue(openDocumentForm(), "Should open form")
let deleteTitle = "Warranty to Delete \(UUID().uuidString.prefix(8))"
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: deleteTitle)
selectCategory(category: "Other")
fillTextField(placeholder: "Item Name", text: "Test Item") // REQUIRED
fillTextField(placeholder: "Provider", text: "Test Provider") // REQUIRED
XCTAssertTrue(submitForm(), "Should create warranty")
sleep(2)
// Open and delete
let warrantyCard = app.staticTexts[deleteTitle]
XCTAssertTrue(warrantyCard.exists, "Warranty should exist")
warrantyCard.tap()
sleep(2)
let deleteButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Delete' OR label CONTAINS[c] 'trash'")).firstMatch
if deleteButton.exists {
deleteButton.tap()
sleep(1)
// Confirm
let confirmButton = app.alerts.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Delete'")).firstMatch
if confirmButton.exists {
confirmButton.tap()
sleep(2)
}
// Verify deleted
sleep(2)
let deletedCard = app.staticTexts[deleteTitle]
XCTAssertFalse(deletedCard.exists, "Deleted warranty should not appear")
}
}
// MARK: Edge Cases and Error Handling
func test19_CancelDocumentCreation() {
navigateToDocumentsTab()
switchToDocumentsTab()
XCTAssertTrue(openDocumentForm(), "Should open form")
// Fill some fields
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: "Cancelled Document")
selectDocumentType(type: "Insurance")
// Cancel instead of save
cancelForm()
// Should not appear in list
sleep(2)
let cancelledDoc = app.staticTexts["Cancelled Document"]
XCTAssertFalse(cancelledDoc.exists, "Cancelled document should not be created")
}
func test20_HandleEmptyDocumentsList() {
navigateToDocumentsTab()
switchToDocumentsTab()
// Apply very specific filter to get empty list
searchFor(text: "NONEXISTENT_DOCUMENT_12345")
sleep(2)
// Should show empty state
let emptyMessage = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'No documents' OR label CONTAINS[c] 'No results' OR label CONTAINS[c] 'empty'")).firstMatch
// Either empty state exists or no items are shown
let hasNoItems = app.cells.count == 0
XCTAssertTrue(emptyMessage.exists || hasNoItems, "Should handle empty documents list gracefully")
clearSearch()
}
func test21_HandleEmptyWarrantiesList() {
navigateToDocumentsTab()
switchToWarrantiesTab()
// Search for non-existent warranty
searchFor(text: "NONEXISTENT_WARRANTY_99999")
sleep(2)
let emptyMessage = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'No warranties' OR label CONTAINS[c] 'No results' OR label CONTAINS[c] 'empty'")).firstMatch
let hasNoItems = app.cells.count == 0
XCTAssertTrue(emptyMessage.exists || hasNoItems, "Should handle empty warranties list gracefully")
clearSearch()
}
func test22_CreateDocumentWithLongTitle() {
navigateToDocumentsTab()
switchToDocumentsTab()
XCTAssertTrue(openDocumentForm(), "Should open form")
let longTitle = "This is a very long document title that exceeds normal length expectations to test how the UI handles lengthy text input " + UUID().uuidString
createdDocumentTitles.append(longTitle)
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: longTitle)
selectDocumentType(type: "Insurance")
XCTAssertTrue(submitForm(), "Should handle long title")
sleep(2)
// Just verify it was created (partial match)
let partialTitle = String(longTitle.prefix(30))
let documentExists = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] '\(partialTitle)'")).firstMatch.exists
XCTAssertTrue(documentExists, "Document with long title should be created")
}
func test23_CreateWarrantyWithSpecialCharacters() {
navigateToDocumentsTab()
switchToWarrantiesTab()
XCTAssertTrue(openDocumentForm(), "Should open form")
let specialTitle = "Warranty w/ Special #Chars: @ & $ % \(UUID().uuidString.prefix(8))"
createdDocumentTitles.append(specialTitle)
selectProperty() // REQUIRED - Select property first
fillTextField(placeholder: "Title", text: specialTitle)
selectCategory(category: "Other")
fillTextField(placeholder: "Item Name", text: "Test @#$ Item") // REQUIRED
fillTextField(placeholder: "Provider", text: "Special & Co.") // REQUIRED
XCTAssertTrue(submitForm(), "Should handle special characters")
sleep(2)
let partialTitle = String(specialTitle.prefix(20))
let warrantyExists = app.staticTexts.containing(NSPredicate(format: "label CONTAINS '\(partialTitle)'")).firstMatch.exists
XCTAssertTrue(warrantyExists, "Warranty with special characters should be created")
}
func test24_RapidTabSwitching() {
navigateToDocumentsTab()
// Rapidly switch between tabs
for _ in 0..<5 {
switchToWarrantiesTab()
usleep(500000) // 0.5 seconds
switchToDocumentsTab()
usleep(500000) // 0.5 seconds
}
// Should remain stable
let warrantiesTab = app.buttons["Warranties"]
let documentsTab = app.buttons["Documents"]
XCTAssertTrue(warrantiesTab.exists && documentsTab.exists, "Should handle rapid tab switching without crashing")
}
func test25_MultipleFiltersCombined() {
navigateToDocumentsTab()
switchToWarrantiesTab()
// Apply multiple filters
toggleActiveFilter() // Turn off active filter
sleep(1)
applyFilter(filterName: "Appliances")
sleep(1)
searchFor(text: "Test")
sleep(2)
// Should apply all filters without crashing
let searchField = app.searchFields.firstMatch
XCTAssertTrue(searchField.exists, "Should handle multiple filters simultaneously")
// Clean up
clearSearch()
sleep(1)
applyFilter(filterName: "All Categories")
sleep(1)
toggleActiveFilter() // Turn active filter back on
}
}
// MARK: - XCUIElement Extension for Clearing Text
extension XCUIElement {
func clearText() {
guard let stringValue = self.value as? String else {
return
}
self.tap()
let deleteString = String(repeating: XCUIKeyboardKey.delete.rawValue, count: stringValue.count)
self.typeText(deleteString)
}
}