wip
This commit is contained in:
346
iosApp/iosAppUITests/ResidenceUITests.swift
Normal file
346
iosApp/iosAppUITests/ResidenceUITests.swift
Normal file
@@ -0,0 +1,346 @@
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user