Files
honeyDueKMP/iosApp/iosAppUITests/ResidenceUITests.swift
Trey t 7dce211681 wip
2025-11-08 16:02:01 -06:00

347 lines
13 KiB
Swift

import XCTest
/// Comprehensive tests for residence management
final class ResidenceUITests: BaseUITest {
override func setUp() {
super.setUp()
// Login before each test
login(username: "testuser", password: "TestPass123!")
let residencesTab = app.tabBars.buttons["Residences"]
XCTAssertTrue(residencesTab.waitForExistence(timeout: 10))
}
// MARK: - List View Tests
func testResidenceListDisplays() {
// Given: User is on residences tab
navigateToTab("Residences")
// Then: Residences list should be displayed
let navigationBar = app.navigationBars["Residences"]
XCTAssertTrue(navigationBar.exists, "Should show residences navigation bar")
}
func testResidenceListShowsProperties() {
// Given: User has residences
navigateToTab("Residences")
// Then: Residence cards should be visible
let residenceCards = app.scrollViews.descendants(matching: .other).matching(NSPredicate(format: "identifier CONTAINS 'ResidenceCard'"))
XCTAssertTrue(residenceCards.count > 0 || app.staticTexts["No residences yet"].exists,
"Should show either residence cards or empty state")
}
func testEmptyStateDisplays() {
// Given: User has no residences (requires test account with no data)
navigateToTab("Residences")
// Then: Empty state should be shown
// Note: This test assumes test user has no residences
let emptyStateText = app.staticTexts["No residences yet"]
let addButton = app.buttons.containing(NSPredicate(format: "label CONTAINS[c] 'Add'")).firstMatch
// Should show either residences or empty state with add button
XCTAssertTrue(emptyStateText.exists || app.cells.count > 0, "Should show content or empty state")
}
// MARK: - Create Residence Tests
func testCreateResidenceFlow() {
// Given: User is on residences screen
navigateToTab("Residences")
// When: User taps add residence button
let addButton = app.navigationBars.buttons.matching(identifier: "plus").firstMatch
if !addButton.exists {
// Try finding add button in other locations
let fabButton = app.buttons["Add Residence"]
if fabButton.exists {
fabButton.tap()
} else {
XCTFail("Could not find add residence button")
}
} else {
addButton.tap()
}
// Then: Add residence form should be displayed
wait(seconds: 1)
let nameField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'name' OR label CONTAINS[c] 'Name'")).firstMatch
XCTAssertTrue(nameField.exists, "Should show residence name field")
// When: User fills in residence details
let timestamp = Int(Date().timeIntervalSince1970)
nameField.tap()
nameField.typeText("Test House \(timestamp)")
let addressField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'address' OR label CONTAINS[c] 'Address'")).firstMatch
if addressField.exists {
addressField.tap()
addressField.typeText("123 Test Street")
}
let cityField = app.textFields.containing(NSPredicate(format: "placeholderValue CONTAINS[c] 'city' OR label CONTAINS[c] 'City'")).firstMatch
if cityField.exists {
cityField.tap()
cityField.typeText("Test City")
}
// When: User saves the residence
let saveButton = app.buttons["Save"]
if saveButton.exists {
saveButton.tap()
}
// Then: User should be returned to list view
// And: New residence should appear in the list
wait(seconds: 2)
let residenceTitle = app.staticTexts["Test House \(timestamp)"]
XCTAssertTrue(residenceTitle.waitForExistence(timeout: 5) || app.navigationBars["Residences"].exists,
"Should show new residence or navigate back to list")
}
func testCreateResidenceValidation() {
// Given: User is on add residence screen
navigateToTab("Residences")
let addButton = app.navigationBars.buttons.matching(identifier: "plus").firstMatch
addButton.tap()
wait(seconds: 1)
// When: User attempts to save without required fields
let saveButton = app.buttons["Save"]
if saveButton.exists {
saveButton.tap()
}
// Then: Validation errors should be shown
let errorMessages = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'required'"))
XCTAssertTrue(errorMessages.count > 0 || !app.navigationBars["Residences"].exists,
"Should show validation errors or prevent saving")
}
// MARK: - View Residence Details Tests
func testViewResidenceDetails() {
// Given: User has residences
navigateToTab("Residences")
wait(seconds: 2)
// When: User taps on a residence
let firstResidence = app.cells.firstMatch
if firstResidence.exists {
firstResidence.tap()
// Then: Residence details should be displayed
wait(seconds: 2)
let detailView = app.scrollViews.firstMatch
XCTAssertTrue(detailView.exists || app.navigationBars.element(boundBy: 1).exists,
"Should show residence details")
}
}
func testResidenceDetailsShowsAllSections() {
// Given: User is viewing residence details
navigateToTab("Residences")
wait(seconds: 2)
let firstResidence = app.cells.firstMatch
if firstResidence.exists {
firstResidence.tap()
wait(seconds: 2)
// Then: All sections should be visible (after scrolling)
let scrollView = app.scrollViews.firstMatch
if scrollView.exists {
// Check for address section
let addressSection = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'Address'")).firstMatch
// Check for tasks section
scrollView.swipeUp()
let tasksSection = app.staticTexts.containing(NSPredicate(format: "label CONTAINS[c] 'Tasks'")).firstMatch
XCTAssertTrue(addressSection.exists || tasksSection.exists, "Should show residence sections")
}
}
}
// MARK: - Edit Residence Tests
func testEditResidenceFlow() {
// Given: User is viewing residence details
navigateToTab("Residences")
wait(seconds: 2)
let firstResidence = app.cells.firstMatch
if firstResidence.exists {
firstResidence.tap()
wait(seconds: 2)
// When: User taps edit button
let editButton = app.navigationBars.buttons["Edit"]
if editButton.exists {
editButton.tap()
wait(seconds: 1)
// Then: Edit form should be displayed
let nameField = app.textFields.containing(NSPredicate(format: "value != nil AND value != ''")).firstMatch
XCTAssertTrue(nameField.exists, "Should show edit form with current values")
// When: User updates the name
if nameField.exists {
app.clearText(in: nameField)
nameField.typeText("Updated House Name")
// When: User saves changes
let saveButton = app.buttons["Save"]
if saveButton.exists {
saveButton.tap()
}
// Then: Changes should be saved and details view updated
wait(seconds: 2)
let updatedName = app.staticTexts["Updated House Name"]
XCTAssertTrue(updatedName.waitForExistence(timeout: 5) || app.navigationBars.element(boundBy: 1).exists,
"Should show updated residence name or details view")
}
}
}
}
func testCancelEditingResidence() {
// Given: User is editing a residence
navigateToTab("Residences")
wait(seconds: 2)
let firstResidence = app.cells.firstMatch
if firstResidence.exists {
firstResidence.tap()
wait(seconds: 2)
let editButton = app.navigationBars.buttons["Edit"]
if editButton.exists {
editButton.tap()
wait(seconds: 1)
// When: User makes changes
let nameField = app.textFields.firstMatch
let originalValue = nameField.value as? String
if nameField.exists {
app.clearText(in: nameField)
nameField.typeText("Temporary Change")
// When: User cancels
let cancelButton = app.buttons["Cancel"]
if cancelButton.exists {
cancelButton.tap()
}
// Then: Changes should be discarded
wait(seconds: 1)
if let original = originalValue {
let originalText = app.staticTexts[original]
XCTAssertTrue(originalText.exists || app.navigationBars.element(boundBy: 1).exists,
"Should discard changes")
}
}
}
}
}
// MARK: - Delete Residence Tests
func testDeleteResidence() {
// Given: User has a residence to delete
navigateToTab("Residences")
wait(seconds: 2)
let initialResidenceCount = app.cells.count
// When: User swipes to delete (if supported)
let firstResidence = app.cells.firstMatch
if firstResidence.exists {
firstResidence.swipeLeft()
let deleteButton = app.buttons["Delete"]
if deleteButton.exists {
deleteButton.tap()
// Confirm deletion if alert appears
let confirmButton = app.alerts.buttons["Delete"]
if confirmButton.exists {
confirmButton.tap()
}
// Then: Residence should be removed
wait(seconds: 2)
let newCount = app.cells.count
XCTAssertTrue(newCount < initialResidenceCount || app.staticTexts["No residences yet"].exists,
"Should remove residence from list")
}
}
}
// MARK: - Navigation Tests
func testNavigateBackFromDetails() {
// Given: User is viewing residence details
navigateToTab("Residences")
wait(seconds: 2)
let firstResidence = app.cells.firstMatch
if firstResidence.exists {
firstResidence.tap()
wait(seconds: 2)
// When: User taps back button
navigateBack()
// Then: User should return to residences list
let navigationBar = app.navigationBars["Residences"]
XCTAssertTrue(navigationBar.waitForExistence(timeout: 3), "Should navigate back to residences list")
}
}
// MARK: - Search and Filter Tests (if implemented)
func testSearchResidences() {
// Given: User has multiple residences
navigateToTab("Residences")
wait(seconds: 2)
// When: User searches for a residence
let searchField = app.searchFields.firstMatch
if searchField.exists {
searchField.tap()
searchField.typeText("Test")
// Then: Results should be filtered
wait(seconds: 1)
let visibleResidences = app.cells.count
XCTAssertTrue(visibleResidences >= 0, "Should show filtered results")
}
}
// MARK: - Pull to Refresh Tests
func testPullToRefreshResidences() {
// Given: User is on residences list
navigateToTab("Residences")
wait(seconds: 2)
// When: User pulls down to refresh
let scrollView = app.scrollViews.firstMatch
if scrollView.exists {
let startPoint = scrollView.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.2))
let endPoint = scrollView.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.8))
startPoint.press(forDuration: 0.1, thenDragTo: endPoint)
// Then: Loading indicator should appear
let loadingIndicator = app.activityIndicators.firstMatch
XCTAssertTrue(loadingIndicator.exists || scrollView.exists, "Should trigger refresh")
}
}
}